diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..ea09a3c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "cairo_jpg"] + path = cairo_jpg + url = https://github.com/rahra/cairo_jpg.git diff --git a/Makefile b/Makefile index 7d2d6dc..7b1cc95 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ CC=gcc -CFLAGS=-O2 -Wall -D_REENTRANT `pkg-config --cflags gtk+-3.0` `pkg-config --cflags libusb-1.0` -LIBS=`pkg-config --libs gtk+-3.0` `pkg-config --libs libusb-1.0` -lm +CFLAGS=-g -O2 -Wall -D_REENTRANT `pkg-config --cflags gtk+-3.0 libusb-1.0 libjpeg` +LIBS=`pkg-config --libs gtk+-3.0 libusb-1.0 libjpeg` -lm -OBJ=flirgtk.o cam-thread.o +OBJ=flirgtk.o cam-thread.o cairo_jpg/src/cairo_jpg.o PRG=flirgtk all: $(PRG) diff --git a/cairo_jpg b/cairo_jpg new file mode 160000 index 0000000..2a0dff5 --- /dev/null +++ b/cairo_jpg @@ -0,0 +1 @@ +Subproject commit 2a0dff5ad313fdb8db3112eaf635bd56516ddf49 diff --git a/cam-thread.c b/cam-thread.c index 6f759b0..de3cefc 100644 --- a/cam-thread.c +++ b/cam-thread.c @@ -69,6 +69,8 @@ int FFC = 0; // detect FFC int buf85pointer = 0; unsigned char buf85[BUF85SIZE]; +extern unsigned char *jpeg_buffer; +extern unsigned int jpeg_size; double @@ -88,6 +90,7 @@ raw2temperature(unsigned short RAW) void vframe(char ep[],char EP_error[], int r, int actual_length, unsigned char buf[], unsigned char *colormap) { + static int fcnt=0; // error handler time_t now1; now1 = time(NULL); @@ -262,7 +265,7 @@ void vframe(char ep[],char EP_error[], int r, int actual_length, unsigned char b fbdata[16*y * 640 + x*16] = color_palette[3 * v + 2]; // B fbdata[(16*y * 640 + x*16)+1] = color_palette[3 * v + 1]; // G fbdata[(16*y * 640 + x*16)+2] = color_palette[3 * v]; // R - // fbdata[(16*y * 640 + x*16)+3] = 0x00; // empty + // fbdata[(16*y * 640 + x*16)+3] = 0x7f; // empty // copy whole 32bit words hor/vert p1 = (unsigned int *)&fbdata[16*y * 640 + x*16]; @@ -308,6 +311,26 @@ void vframe(char ep[],char EP_error[], int r, int actual_length, unsigned char b // write video to v4l2loopback(s) // write(fdwr0, fb_proc, framesize0); // gray scale Thermal Image //write(fdwr1, &buf85[28+ThermalSize], JpgSize); // jpg Visual Image +#if 0 + fprintf(stderr, "jpgsize %d\n", JpgSize); + { + char fname[64]; + int fdf; + + snprintf(fname, 64, "frame-%04d.jpg", fcnt++); + fdf=open(fname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + write (fdf, &buf85[28+ThermalSize], JpgSize); + close(fdf); + } +#endif + if (jpeg_size == 0 && JpgSize > 0) { + //unsigned char bla[BUF85SIZE]; + + jpeg_size=JpgSize; + jpeg_buffer=(unsigned char *)malloc(jpeg_size); + // fprintf(stderr, "jpgsize %d %d\n", JpgSize, jpeg_size); + memcpy(jpeg_buffer, &buf85[28+ThermalSize], jpeg_size); + } if (strncmp ((char *)&buf85[28+ThermalSize+JpgSize+17],"FFC",3)==0) { FFC=1; // drop all FFC frames diff --git a/flirgtk.c b/flirgtk.c index c053a0b..f01afb1 100644 --- a/flirgtk.c +++ b/flirgtk.c @@ -19,6 +19,13 @@ #include +#include + #include + #include + + +#include "cairo_jpg/src/cairo_jpg.h" + #include "palettes/15.h" #include "palettes/17.h" #include "palettes/7.h" @@ -44,6 +51,10 @@ gboolean flir_run = FALSE; gpointer cam_thread_main(gpointer user_data); extern double t_min, t_max, t_center; +#define BUF85SIZE 1048576 +unsigned char *jpeg_buffer; +unsigned int jpeg_size=0; + void draw_palette(void); @@ -61,7 +72,7 @@ int stride; gtk_widget_get_allocation (widget, &allocation); // g_printerr("configure event %d x %d\n", allocation.width, allocation.height); - stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, 640); + stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, 640); // g_printerr("stride %d\n", stride); surface = cairo_image_surface_create_for_data (fbuffer, CAIRO_FORMAT_RGB24, @@ -81,53 +92,92 @@ draw_event (GtkWidget *widget, cairo_t *cr, gpointer data) { +char tdisp[16]; +cairo_surface_t *jpeg_surface; +static int fcnt=0; + // g_printerr("draw event\n"); + // first draw the frame buffer containing the IR frame +#if 1 + if (jpeg_size != 0) { + // g_printerr(" draw event %d\n", jpeg_size); + jpeg_surface=cairo_image_surface_create_from_jpeg_mem(jpeg_buffer, jpeg_size); +// cairo_scale (cr, (1./2.25), (1./2.25)); + cairo_set_source_surface (cr, jpeg_surface, 0, 0); + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_paint (cr); + cairo_surface_destroy (jpeg_surface); + jpeg_size=0; + } +#endif cairo_set_source_surface (cr, surface, 0, 0); + cairo_set_operator (cr, CAIRO_OPERATOR_OVER); cairo_paint (cr); +#if 1 + // then draw decoration +// cairo_scale (cr, 1, 1); + + // crosshair in the center + cairo_set_line_width (cr, 3); + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_move_to(cr, 320, 200); + cairo_line_to(cr, 320, 280); + cairo_stroke (cr); + cairo_move_to(cr, 280, 240); + cairo_line_to(cr, 360, 240); + cairo_stroke (cr); + cairo_set_line_width (cr, 1); + cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); + cairo_move_to(cr, 320, 200); + cairo_line_to(cr, 320, 280); + cairo_stroke (cr); + cairo_move_to(cr, 280, 240); + cairo_line_to(cr, 360, 240); + cairo_stroke (cr); + + // print center temperature near crosshair + snprintf(tdisp, 16, "%.1f°C", t_center); + cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); + cairo_select_font_face (cr, "Sans", + CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_font_size (cr, 24); + // cairo_text_extents (cr, "a", &te); + cairo_move_to (cr, 330, 220); + cairo_show_text (cr, tdisp); + + // update palette scale temperature range + snprintf(tdisp, 16, "%.1f°C", t_min); + cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); + cairo_select_font_face (cr, "Sans", + CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_font_size (cr, 18); + cairo_move_to (cr, 102, 496); + cairo_show_text (cr, tdisp); + + snprintf(tdisp, 16, "%.1f°C", t_max); + cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); + cairo_select_font_face (cr, "Sans", + CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_font_size (cr, 18); + cairo_move_to (cr, 440, 496); + cairo_show_text (cr, tdisp); +#endif return FALSE; } -#include "font5x7.h" -void font_write(unsigned char *fb, int x, int y, const char *string) -{ -int rx, ry, v; - - while (*string) { - for (ry = 0; ry < 5; ++ry) { - for (rx = 0; rx < 7; ++rx) { - v = (font5x7_basic[((*string) & 0x7F) - CHAR_OFFSET][ry] >> (rx)) & 1; - // fb[(y+ry) * 160 + (x + rx)] = v ? 0 : 0xFF; // black / white - fb[((y+rx)*4) * 640 + (x + ry)*4] = v ? 0xff : 0x00; // black / white - fb[((y+rx)*4) * 640 + (x + ry)*4 +1] = v ? 0xff : 0x00; // black / white - fb[((y+rx)*4) * 640 + (x + ry)*4 +2] = v ? 0xff : 0x00; // black / white - // fb[(y+rx) * 160 + (x + ry)] = v ? 0 : fb[(y+rx) * 160 + (x + ry)]; // transparent - } - } - string++; - x += 6; - } -} void update_fb(void) { -char tstr[16]; - - // g_printerr("min %.1f center %.1f max %.1f\r", t_min, t_center, t_max); - - snprintf(tstr, 16, "%.1f", t_min); - font_write(fbdata, 140, 486, tstr); - snprintf(tstr, 16, "%.1f", t_max); - font_write(fbdata, 440, 486, tstr); gtk_widget_queue_draw(image_darea); } void store_shot_clicked(GtkWidget *button, gpointer user_data) { - +//cairo_surface_t *cairo_get_target (cairo_t *cr); cairo_surface_write_to_png (surface, "shot.png"); } diff --git a/font5x7.h b/font5x7.h deleted file mode 100644 index b123de3..0000000 --- a/font5x7.h +++ /dev/null @@ -1,128 +0,0 @@ -/* From https://ccrma.stanford.edu/courses/250a-fall-2003/docs/avrlib-new/ */ - -/* Original header: */ - -/*! \file font5x7.h \brief Graphic LCD Font (Ascii Characters). */ -//***************************************************************************** -// -// File Name: 'font5x7.h' -// Title: Graphic LCD Font (Ascii Charaters) -// Author: Pascal Stang -// Date: 10/19/2001 -// Revised: 10/19/2001 -// Version: 0.1 -// Target MCU: Atmel AVR -// Editor Tabs: 4 -// -//***************************************************************************** - -/* Original license in cmdline.c: */ - -// This code is distributed under the GNU Public License -// which can be found at http://www.gnu.org/licenses/gpl.txt - -/* Since the original license does not specify the GPL version it is safe */ -/* to assume that it can be distributed under GPL version 1 or any later */ -/* version. */ - -#define MAX_CHARS 96 -#define CHAR_OFFSET 0x20 - -unsigned char font5x7_basic[MAX_CHARS][5] = { - {0x00, 0x00, 0x00, 0x00, 0x00}, // (space) - {0x00, 0x00, 0x5F, 0x00, 0x00}, // ! - {0x00, 0x07, 0x00, 0x07, 0x00}, // " - {0x14, 0x7F, 0x14, 0x7F, 0x14}, // # - {0x24, 0x2A, 0x7F, 0x2A, 0x12}, // $ - {0x23, 0x13, 0x08, 0x64, 0x62}, // % - {0x36, 0x49, 0x55, 0x22, 0x50}, // & - {0x00, 0x05, 0x03, 0x00, 0x00}, // ' - {0x00, 0x1C, 0x22, 0x41, 0x00}, // ( - {0x00, 0x41, 0x22, 0x1C, 0x00}, // ) - {0x08, 0x2A, 0x1C, 0x2A, 0x08}, // * - {0x08, 0x08, 0x63, 0x08, 0x08}, // + {0x08, 0x08, 0x3E, 0x08, 0x08} - {0x00, 0x50, 0x30, 0x00, 0x00}, // , - {0x08, 0x08, 0x08, 0x08, 0x08}, // - - {0x00, 0x60, 0x60, 0x00, 0x00}, // . - {0x20, 0x10, 0x08, 0x04, 0x02}, // / - {0x3E, 0x51, 0x49, 0x45, 0x3E}, // 0 - {0x00, 0x42, 0x7F, 0x40, 0x00}, // 1 - {0x42, 0x61, 0x51, 0x49, 0x46}, // 2 - {0x21, 0x41, 0x45, 0x4B, 0x31}, // 3 - {0x18, 0x14, 0x12, 0x7F, 0x10}, // 4 - {0x27, 0x45, 0x45, 0x45, 0x39}, // 5 - {0x3C, 0x4A, 0x49, 0x49, 0x30}, // 6 - {0x01, 0x71, 0x09, 0x05, 0x03}, // 7 - {0x36, 0x49, 0x49, 0x49, 0x36}, // 8 - {0x06, 0x49, 0x49, 0x29, 0x1E}, // 9 - {0x00, 0x36, 0x36, 0x00, 0x00}, // : - {0x00, 0x56, 0x36, 0x00, 0x00}, // ; - {0x00, 0x08, 0x14, 0x22, 0x41}, // < - {0x14, 0x14, 0x14, 0x14, 0x14}, // = - {0x41, 0x22, 0x14, 0x08, 0x00}, // > - {0x02, 0x01, 0x51, 0x09, 0x06}, // ? - {0x32, 0x49, 0x79, 0x41, 0x3E}, // @ - {0x7E, 0x11, 0x11, 0x11, 0x7E}, // A - {0x7F, 0x49, 0x49, 0x49, 0x36}, // B - {0x3E, 0x41, 0x41, 0x41, 0x22}, // C - {0x7F, 0x41, 0x41, 0x22, 0x1C}, // D - {0x7F, 0x49, 0x49, 0x49, 0x41}, // E - {0x7F, 0x09, 0x09, 0x01, 0x01}, // F - {0x3E, 0x41, 0x41, 0x51, 0x32}, // G - {0x7F, 0x08, 0x08, 0x08, 0x7F}, // H - {0x00, 0x41, 0x7F, 0x41, 0x00}, // I - {0x20, 0x40, 0x41, 0x3F, 0x01}, // J - {0x7F, 0x08, 0x14, 0x22, 0x41}, // K - {0x7F, 0x40, 0x40, 0x40, 0x40}, // L - {0x7F, 0x02, 0x04, 0x02, 0x7F}, // M - {0x7F, 0x04, 0x08, 0x10, 0x7F}, // N - {0x3E, 0x41, 0x41, 0x41, 0x3E}, // O - {0x7F, 0x09, 0x09, 0x09, 0x06}, // P - {0x3E, 0x41, 0x51, 0x21, 0x5E}, // Q - {0x7F, 0x09, 0x19, 0x29, 0x46}, // R - {0x46, 0x49, 0x49, 0x49, 0x31}, // S - {0x01, 0x01, 0x7F, 0x01, 0x01}, // T - {0x3F, 0x40, 0x40, 0x40, 0x3F}, // U - {0x1F, 0x20, 0x40, 0x20, 0x1F}, // V - {0x7F, 0x20, 0x18, 0x20, 0x7F}, // W - {0x63, 0x14, 0x08, 0x14, 0x63}, // X - {0x03, 0x04, 0x78, 0x04, 0x03}, // Y - {0x61, 0x51, 0x49, 0x45, 0x43}, // Z - {0x00, 0x00, 0x7F, 0x41, 0x41}, // [ - {0x02, 0x04, 0x08, 0x10, 0x20}, // "\" - {0x41, 0x41, 0x7F, 0x00, 0x00}, // ] - {0x04, 0x02, 0x01, 0x02, 0x04}, // ^ - {0x40, 0x40, 0x40, 0x40, 0x40}, // _ - {0x00, 0x01, 0x02, 0x04, 0x00}, // ` - {0x20, 0x54, 0x54, 0x54, 0x78}, // a - {0x7F, 0x48, 0x44, 0x44, 0x38}, // b - {0x38, 0x44, 0x44, 0x44, 0x20}, // c - {0x38, 0x44, 0x44, 0x48, 0x7F}, // d - {0x38, 0x54, 0x54, 0x54, 0x18}, // e - {0x08, 0x7E, 0x09, 0x01, 0x02}, // f - {0x08, 0x14, 0x54, 0x54, 0x3C}, // g - {0x7F, 0x08, 0x04, 0x04, 0x78}, // h - {0x00, 0x44, 0x7D, 0x40, 0x00}, // i - {0x20, 0x40, 0x44, 0x3D, 0x00}, // j - {0x00, 0x7F, 0x10, 0x28, 0x44}, // k - {0x00, 0x41, 0x7F, 0x40, 0x00}, // l - {0x7C, 0x04, 0x18, 0x04, 0x78}, // m - {0x7C, 0x08, 0x04, 0x04, 0x78}, // n - {0x38, 0x44, 0x44, 0x44, 0x38}, // o - {0x7C, 0x14, 0x14, 0x14, 0x08}, // p - {0x08, 0x14, 0x14, 0x18, 0x7C}, // q - {0x7C, 0x08, 0x04, 0x04, 0x08}, // r - {0x48, 0x54, 0x54, 0x54, 0x20}, // s - {0x04, 0x3F, 0x44, 0x40, 0x20}, // t - {0x3C, 0x40, 0x40, 0x20, 0x7C}, // u - {0x1C, 0x20, 0x40, 0x20, 0x1C}, // v - {0x3C, 0x40, 0x30, 0x40, 0x3C}, // w - {0x44, 0x28, 0x10, 0x28, 0x44}, // x - {0x0C, 0x50, 0x50, 0x50, 0x3C}, // y - {0x44, 0x64, 0x54, 0x4C, 0x44}, // z - {0x00, 0x08, 0x36, 0x41, 0x00}, // { - {0x00, 0x00, 0x7F, 0x00, 0x00}, // | - {0x00, 0x41, 0x36, 0x08, 0x00}, // } - {0x08, 0x08, 0x2A, 0x1C, 0x08}, // -> - {0x08, 0x1C, 0x2A, 0x08, 0x08}, // <- -};