]> git.zerfleddert.de Git - rigol/blobdiff - png.c
add png output for screenshots
[rigol] / png.c
diff --git a/png.c b/png.c
index accf41540995ca4acee6274414e99790c7f0cb0f..7606f2bb5f7868895b96fd811f242f9824f175a5 100644 (file)
--- 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);
 
Impressum, Datenschutz