From e8e713c3a536c59f94d6402d852f353e34fac2de Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Sun, 6 Jun 2010 12:10:56 +0200 Subject: [PATCH] add png output for screenshots --- .gitignore | 1 + png.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++------- rigol.c | 35 ++++----------------- 3 files changed, 86 insertions(+), 41 deletions(-) diff --git a/.gitignore b/.gitignore index b8d6cba..7dae92c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ raw2gp rigol rigol.o png.o +screen_*.png diff --git a/png.c b/png.c index accf415..7606f2b 100644 --- a/png.c +++ b/png.c @@ -7,6 +7,10 @@ #include "png.h" +#define CHUNK 16384 +#define WIDTH 320 +#define HEIGHT 234 + /* Table of CRCs of all 8-bit messages. */ static unsigned long crc_table[256]; @@ -59,25 +63,30 @@ static unsigned long crc(unsigned char *buf, int len) unsigned char *lcd2png(unsigned char *lcd, int *len) { - unsigned char screen_conv[320*234*3]; + unsigned char screen_conv[(WIDTH*HEIGHT*3)+HEIGHT]; /* 320*234 RGB + scanline filter byte */ + unsigned char *pos; unsigned char lut[256][3]; + unsigned char *screen_deflated; + int deflated_size; unsigned char *image; unsigned char *outpos; static const unsigned char png[] = {137, 80, 78, 71, 13, 10, 26, 10}; + static unsigned char idat[] = {'I', 'D', 'A', 'T'}; + static unsigned char iend[] = {'I', 'E', 'N', 'D'}; static unsigned char ihdr[] = {'I', 'H', 'D', 'R', 0x00, 0x00, 0x01, 0x40, /* 320 - Width */ 0x00, 0x00, 0x00, 0xea, /* 234 - Height */ 0x08, /* Bit depth */ 0x02, /* RGB Truecolor, Colour type */ 0x00, /* Deflate, Compression method */ - 0x00, /* None, Filter method */ + 0x00, /* Adaptive, Filter method */ 0x00 /* No interlace, Interlace method */ }; - static unsigned char idat[] = {'I', 'D', 'A', 'T'}; - static unsigned char iend[] = {'I', 'E', 'N', 'D'}; uint32_t l; int i; + int ret; int toalloc = 0; + int flush; z_stream strm; for(i = 0; i < 256; i++) { @@ -86,22 +95,68 @@ unsigned char *lcd2png(unsigned char *lcd, int *len) lut[i][2] = (((i & 7) * 0x49) >> 1); } - for(i = 0; i < sizeof(screen_conv); i += 3) { - screen_conv[i] = lut[lcd[i/3]][0]; - screen_conv[i+1] = lut[lcd[i/3]][1]; - screen_conv[i+2] = lut[lcd[i/3]][2]; + pos = screen_conv; + for(i = 0; i < (WIDTH*HEIGHT); i++) { + if ((i % WIDTH) == 0) { + *pos++ = 0x00; /* No adaptive filter */ + } + *pos++ = lut[lcd[i]][0]; + *pos++ = lut[lcd[i]][1]; + *pos++ = lut[lcd[i]][2]; } strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; - if (deflateInit(&strm, 9) != Z_OK) { + if (deflateInit(&strm, Z_BEST_COMPRESSION) != Z_OK) { perror("deflateInit"); exit(EXIT_FAILURE); } + strm.avail_in = sizeof(screen_conv); + strm.next_in = screen_conv; + + toalloc = 0; + screen_deflated = NULL; + flush = Z_NO_FLUSH; + + do { + if (strm.avail_out == 0) { + toalloc += CHUNK; + screen_deflated = realloc(screen_deflated, toalloc); + if (screen_deflated == NULL) { + perror("realloc"); + exit(EXIT_FAILURE); + } + + strm.avail_out = CHUNK; + strm.next_out = screen_deflated + (toalloc - CHUNK); + } + + ret = deflate(&strm, flush); + if (ret == Z_STREAM_ERROR) { + perror("deflate"); + exit(EXIT_FAILURE); + } + + if(strm.avail_in == 0) { + flush = Z_FINISH; + } + } while(ret != Z_STREAM_END); + deflated_size = toalloc - strm.avail_out; - image = malloc(320*234*2); /* TODO: FIXME! */ + deflateEnd(&strm); + + + image = malloc(sizeof(png) + + sizeof(ihdr) + 8 + /* 8 = length, csum */ + sizeof(idat) + deflated_size + 8 + + sizeof(iend) + 8); + + if (image == NULL) { + perror("malloc"); + } + outpos = image; memcpy(outpos, png, sizeof(png)); outpos += sizeof(png); @@ -111,7 +166,19 @@ unsigned char *lcd2png(unsigned char *lcd, int *len) outpos += sizeof(l); memcpy(outpos, ihdr, sizeof(ihdr)); outpos += sizeof(ihdr); - l = crc(ihdr, sizeof(ihdr)); + l = htonl(crc(ihdr, sizeof(ihdr))); + memcpy(outpos, &l, sizeof(l)); + outpos += sizeof(l); + + l = htonl(deflated_size); + memcpy(outpos, &l, sizeof(l)); + outpos += sizeof(l); + memcpy(outpos, idat, sizeof(idat)); + outpos += sizeof(idat); + memcpy(outpos, screen_deflated, deflated_size); + free(screen_deflated); + outpos +=deflated_size; + l = htonl(crc(outpos-deflated_size-sizeof(idat), deflated_size+sizeof(idat))); memcpy(outpos, &l, sizeof(l)); outpos += sizeof(l); @@ -120,7 +187,7 @@ unsigned char *lcd2png(unsigned char *lcd, int *len) outpos += sizeof(l); memcpy(outpos, iend, sizeof(iend)); outpos += sizeof(iend); - l = crc(iend, sizeof(iend)); + l = htonl(crc(iend, sizeof(iend))); memcpy(outpos, &l, sizeof(l)); outpos += sizeof(l); diff --git a/rigol.c b/rigol.c index 389253f..818b7ea 100644 --- a/rigol.c +++ b/rigol.c @@ -302,15 +302,12 @@ void do_get_buf (struct usb_dev_handle *sc) void do_get_screen(struct usb_dev_handle *sc) { unsigned char screen[320*234]; - unsigned char screen_conv[320*234*3]; - unsigned char lut[256][3]; time_t lt; char filename[256]; unsigned char *png; - int i; + int imglen; int l; int fd; - FILE *fp; pid_t display; /* Hide "RMT" from screen */ @@ -323,25 +320,11 @@ void do_get_screen(struct usb_dev_handle *sc) printf ("hmm. didnt' get %d bytes, but %d\n\n", sizeof(screen), l); } - for(i = 0; i < 256; i++) { - lut[i][0] = ((i >> 6) * 0x55); - lut[i][1] = ((((i >> 3) & 7) * 0x49) >> 1); - lut[i][2] = (((i & 7) * 0x49) >> 1); - } - - for(i = 0; i < sizeof(screen_conv); i += 3) { - screen_conv[i] = lut[screen[i/3]][0]; - screen_conv[i+1] = lut[screen[i/3]][1]; - screen_conv[i+2] = lut[screen[i/3]][2]; - } - - lt = time(NULL); - strftime(filename, sizeof(filename), "screen_%Y%m%d-%H%M%S.ppm", localtime(<)); - - fp = fopen (filename, "w"); - fprintf(fp, "P6\n320 234\n255\n"); - fwrite(screen_conv, sizeof(screen_conv), 1, fp); - fclose (fp); + strftime(filename, sizeof(filename), "screen_%Y%m%d-%H%M%S.png", localtime(<)); + fd=open(filename, O_CREAT|O_WRONLY, 0644); + png = lcd2png(screen, &imglen); + write(fd, png, imglen); + close(fd); printf("Waveform saved as %s\n", filename); @@ -357,12 +340,6 @@ void do_get_screen(struct usb_dev_handle *sc) default: break; } - - strftime(filename, sizeof(filename), "screen_%Y%m%d-%H%M%S.png", localtime(<)); - fd=open(filename, O_CREAT|O_WRONLY, 0644); - png = lcd2png(screen, &i); - write(fd, png, i); - close(fd); } void child_reaper(int sig) -- 2.39.2