diff
patches/libpng.patch | 152 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 152 insertions(+)
diff --git a/patches/libpng.patch b/patches/libpng.patch
new file mode 100644
index 0000000..20ce87f
--- /dev/null
+++ b/patches/libpng.patch
@@ -0,0 +1,152 @@
+--- a/ss.c
++++ b/ss.c
+@@ -1,8 +1,11 @@
+ #include <X11/Xlib.h>
+ #include <X11/Xutil.h>
+
++#include <png.h>
++
+ #include <stdio.h>
+ #include <stdlib.h>
++#include <string.h>
+
+ static unsigned long
+ lowbit(unsigned long x)
+@@ -27,6 +30,69 @@
+ return (unsigned char)((v * 255UL + (max / 2UL)) / max);
+ }
+
++static int
++haspngext(const char *path)
++{
++ size_t n;
++
++ n = strlen(path);
++ if (n < 4)
++ return 0;
++ return !strcmp(path + n - 4, ".png");
++}
++
++static int
++writepng(FILE *f, XImage *img, unsigned int w, unsigned int h)
++{
++ png_structp png;
++ png_infop info;
++ unsigned char *row;
++ int ix;
++ int iy;
++
++ png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
++ if (png == NULL)
++ return 0;
++ info = png_create_info_struct(png);
++ if (info == NULL) {
++ png_destroy_write_struct(&png, NULL);
++ return 0;
++ }
++ if (setjmp(png_jmpbuf(png))) {
++ png_destroy_write_struct(&png, &info);
++ return 0;
++ }
++
++ png_init_io(png, f);
++ png_set_IHDR(png, info, w, h, 8,
++ PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
++ PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
++ png_write_info(png, info);
++
++ row = malloc((size_t)w * 3U);
++ if (row == NULL) {
++ png_destroy_write_struct(&png, &info);
++ return 0;
++ }
++
++ for (iy = 0; iy < (int)h; iy++) {
++ for (ix = 0; ix < (int)w; ix++) {
++ unsigned long p;
++
++ p = XGetPixel(img, ix, iy);
++ row[ix * 3 + 0] = chan(p, img->red_mask);
++ row[ix * 3 + 1] = chan(p, img->green_mask);
++ row[ix * 3 + 2] = chan(p, img->blue_mask);
++ }
++ png_write_row(png, row);
++ }
++
++ png_write_end(png, info);
++ free(row);
++ png_destroy_write_struct(&png, &info);
++ return 1;
++}
++
+ int
+ main(int argc, char **argv)
+ {
+@@ -45,7 +111,7 @@
+ char tail;
+
+ if (argc != 3) {
+- fprintf(stderr, "usage: ss WIDTHxHEIGHT+X+Y file.ppm\n");
++ fprintf(stderr, "usage: ss WIDTHxHEIGHT+X+Y file.(ppm|png)\n");
+ return 1;
+ }
+ if (sscanf(argv[1], "%ux%u+%d+%d%c", &w, &h, &x, &y, &tail) != 4 || w == 0 || h == 0) {
+@@ -81,22 +147,32 @@
+ return 1;
+ }
+
+- fprintf(f, "P6\n%u %u\n255\n", w, h);
+- for (iy = 0; iy < (int)h; iy++) {
+- for (ix = 0; ix < (int)w; ix++) {
+- unsigned long p;
+- unsigned char rgb[3];
++ if (haspngext(argv[2])) {
++ if (!writepng(f, img, w, h)) {
++ fprintf(stderr, "png write failed: %s\n", argv[2]);
++ fclose(f);
++ XDestroyImage(img);
++ XCloseDisplay(dpy);
++ return 1;
++ }
++ } else {
++ fprintf(f, "P6\n%u %u\n255\n", w, h);
++ for (iy = 0; iy < (int)h; iy++) {
++ for (ix = 0; ix < (int)w; ix++) {
++ unsigned long p;
++ unsigned char rgb[3];
+
+- p = XGetPixel(img, ix, iy);
+- rgb[0] = chan(p, img->red_mask);
+- rgb[1] = chan(p, img->green_mask);
+- rgb[2] = chan(p, img->blue_mask);
+- if (fwrite(rgb, 1, 3, f) != 3) {
+- fprintf(stderr, "write failed: %s\n", argv[2]);
+- fclose(f);
+- XDestroyImage(img);
+- XCloseDisplay(dpy);
+- return 1;
++ p = XGetPixel(img, ix, iy);
++ rgb[0] = chan(p, img->red_mask);
++ rgb[1] = chan(p, img->green_mask);
++ rgb[2] = chan(p, img->blue_mask);
++ if (fwrite(rgb, 1, 3, f) != 3) {
++ fprintf(stderr, "write failed: %s\n", argv[2]);
++ fclose(f);
++ XDestroyImage(img);
++ XCloseDisplay(dpy);
++ return 1;
++ }
+ }
+ }
+ }
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ CFLAGS = -std=c89 -Wall -Wextra -Werror -pedantic
+ CPPFLAGS = -I/usr/X11R6/include
+ LDFLAGS = -L/usr/X11R6/lib
+-LDLIBS = -lX11
++LDLIBS = -lX11 -lpng
+
+ all: ss
+