shithub: pdffs

Download patch

ref: ef5d7bc12ccaa8052b1b1705e5a7d6c87ad4eefe
parent: 7c3dae6ee98d99ea92bc06a830acf59f40108d45
author: Sigrid Solveig Haflínudóttir <ftrvxmtrx@gmail.com>
date: Sun Nov 22 15:18:38 EST 2020

lzw and flate filters: use common predict logic

--- a/f_flate.c
+++ b/f_flate.c
@@ -3,70 +3,8 @@
 #include <flate.h>
 #include "pdf.h"
 
-typedef struct FlateParms FlateParms;
 
-struct FlateParms {
-	int predictor;
-	int columns;
-};
-
-static uchar 
-paeth(uchar a, uchar b, uchar c)
-{
-	int p, pa, pb, pc;
-
-	p = a + b - c;
-	pa = abs(p - a);
-	pb = abs(p - b);
-	pc = abs(p - c);
-
-	if(pa <= pb && pa <= pc)
-		return a;
-	return pb <= pc ? b : c;
-}
-
 static int
-pngunpredict(int pred, uchar *buf, uchar *up, int len)
-{
-	int i;
-
-	switch(pred){
-	case 0: /* None */
-		break;
-
-	case 1: /* Sub */
-		for(i = 1; i < len; ++i)
-			buf[i] += buf[i-1];
-		break;
-
-	case 2: /* Up */
-		for(i = 0; i < len; ++i)
-			buf[i] += up[i];
-		break;
-
-	case 3: /* Average */
-		buf[0] += up[0]/2;
-		for(i = 1; i < len; ++i)
-			buf[i] += (buf[i-1]+up[i])/2;
-		break;
-
-	case 4: /* Paeth */
-		buf[0] += paeth(0, up[0], 0);
-		for(i = 0; i < len; ++i)
-			buf[i] += paeth(buf[i-1], up[i], up[i-1]);
-		break;
-
-	/* FIXME 5 optimum??? */
-
-	default:
-		werrstr("unsupported predictor %d", pred);
-		return -1;
-	}
-
-	return 0;
-}
-
-static int
 bw(void *aux, void *d, int n)
 {
 	return bufput(aux, d, n);
@@ -83,12 +21,8 @@
 static int
 flreadall(void *aux, Buffer *bi, Buffer *bo)
 {
-	int r, i, rows, n;
-	FlateParms *fp;
-	uchar *x, *y, *zero;
+	int r;
 
-	fp = aux;
-
 	do{
 		r = inflatezlib(bo, bw, bi, bget);
 	}while(r == FlateOk && !bufeof(bi));
@@ -97,66 +31,13 @@
 		werrstr("%s", flateerr(r));
 		return -1;
 	}
-	r = 0;
 
-	/* 7.4.4.4 LZW and Flate predictor functions */
-	if(fp->predictor >= 10 && fp->columns > 0){
-		n = fp->columns + 1;
-		rows = bo->sz/n;
-		x = bo->b;
-		y = bo->b;
-		zero = mallocz(fp->columns, 1);
-		for(i = r = 0; i < rows && r == 0; i++, x += n, y += n)
-			r = pngunpredict(x[0], x+1, i < 1 ? zero : y+1-n, fp->columns);
-		free(zero);
-
-		x = bo->b;
-		y = bo->b+1;
-		for(i = 0; i < rows; i++, x += fp->columns, y += n)
-			memmove(x, y, fp->columns);
-		bo->sz -= rows;
-	}
-
-	return r;
+	return unpredict(aux, bo);
 }
 
-static int
-flopen(Filter *f, Object *o)
-{
-	Object *parms;
-	FlateParms *fp;
-	int predictor, columns;
-
-	parms = dictget(o, "DecodeParms");
-	predictor = dictint(parms, "Predictor");
-	columns = dictint(parms, "Columns");
-	if((predictor >= 2 && predictor < 10) || predictor >= 15){
-		werrstr("unsupported flate predictor %d", predictor);
-		return -1;
-	}
-	if(predictor >= 10 && predictor <= 15 && columns < 1){
-		werrstr("invalid columns %d for predictor %d", columns, predictor);
-		return -1;
-	}
-
-	if((fp = malloc(sizeof(FlateParms))) == nil)
-		return -1;
-	fp->predictor = predictor;
-	fp->columns = columns;
-	f->aux = fp;
-
-	return 0;
-}
-
-static void
-flclose(Filter *f)
-{
-	free(f->aux);
-}
-
 Filter filterFlate = {
 	.name = "FlateDecode",
 	.readall = flreadall,
-	.open = flopen,
-	.close = flclose,
+	.open = flopenpredict,
+	.close = flclosepredict,
 };
--- a/f_lzw.c
+++ b/f_lzw.c
@@ -121,8 +121,6 @@
 	uchar *in;
 	Tb tb;
 
-	USED(aux);
-
 	memset(&tb, 0, sizeof(tb));
 	in = bufdata(bi, &insz);
 	width = 9;
@@ -155,10 +153,12 @@
 	tbfree(&tb);
 	bi->off = bi->sz;
 
-	return 0;
+	return unpredict(aux, bo);
 }
 
 Filter filterLZW = {
 	.name = "LZWDecode",
 	.readall = flreadall,
+	.open = flopenpredict,
+	.close = flclosepredict,
 };
--- a/mkfile
+++ b/mkfile
@@ -7,12 +7,12 @@
 	buffer.$O\
 	dict.$O\
 	eval.$O\
-	f_dct.$O\
 	f_ascii85.$O\
 	f_asciihex.$O\
 	f_ccittfax.$O\
 	f_crypt.$O\
 	f_dct.$O\
+	f_dct.$O\
 	f_flate.$O\
 	f_jbig2.$O\
 	f_jpx.$O\
@@ -25,6 +25,7 @@
 	object.$O\
 	pdf.$O\
 	pdffs.$O\
+	predict.$O\
 	stream.$O\
 	string.$O\
 	xref.$O\
--- a/pdf.h
+++ b/pdf.h
@@ -15,6 +15,8 @@
 typedef struct KeyValue KeyValue;
 typedef struct Object Object;
 typedef struct Pdf Pdf;
+typedef struct PredictParms PredictParms;
+#pragma incomplete PredictParms;
 typedef struct Stream Stream;
 typedef struct Xref Xref;
 
@@ -185,6 +187,11 @@
 Filter *filteropen(char *name, Object *o);
 int filterrun(Filter *f, Buffer *bi, Buffer *bo);
 void filterclose(Filter *f);
+
+/* 7.4.4.4 LZW and Flate predictor functions */
+int unpredict(PredictParms *pp, Buffer *bo);
+int flopenpredict(Filter *f, Object *o);
+void flclosepredict(Filter *f);
 
 void bufinit(Buffer *b, uchar *d, int sz);
 void buffree(Buffer *b);
--- /dev/null
+++ b/predict.c
@@ -1,0 +1,128 @@
+#include <u.h>
+#include <libc.h>
+#include "pdf.h"
+
+struct PredictParms {
+	int predictor;
+	int columns;
+};
+
+static uchar 
+paeth(uchar a, uchar b, uchar c)
+{
+	int p, pa, pb, pc;
+
+	p = a + b - c;
+	pa = abs(p - a);
+	pb = abs(p - b);
+	pc = abs(p - c);
+
+	if(pa <= pb && pa <= pc)
+		return a;
+	return pb <= pc ? b : c;
+}
+
+static int
+pngunpredict(int pred, uchar *buf, uchar *up, int len)
+{
+	int i;
+
+	switch(pred){
+	case 0: /* None */
+		break;
+
+	case 1: /* Sub */
+		for(i = 1; i < len; ++i)
+			buf[i] += buf[i-1];
+		break;
+
+	case 2: /* Up */
+		for(i = 0; i < len; ++i)
+			buf[i] += up[i];
+		break;
+
+	case 3: /* Average */
+		buf[0] += up[0]/2;
+		for(i = 1; i < len; ++i)
+			buf[i] += (buf[i-1]+up[i])/2;
+		break;
+
+	case 4: /* Paeth */
+		buf[0] += paeth(0, up[0], 0);
+		for(i = 0; i < len; ++i)
+			buf[i] += paeth(buf[i-1], up[i], up[i-1]);
+		break;
+
+	/* FIXME 5 optimum??? */
+
+	default:
+		werrstr("unsupported predictor %d", pred);
+		return -1;
+	}
+
+	return 0;
+}
+
+int
+unpredict(PredictParms *pp, Buffer *bo)
+{
+	uchar *x, *y, *zero;
+	int i, r, rows, n;
+
+	if(pp->predictor < 10 || pp->columns < 1)
+		return 0;
+
+	n = pp->columns + 1;
+	rows = bo->sz/n;
+	x = bo->b;
+	y = bo->b;
+	zero = mallocz(pp->columns, 1);
+	for(i = r = 0; i < rows && r == 0; i++, x += n, y += n)
+		r = pngunpredict(x[0], x+1, i < 1 ? zero : y+1-n, pp->columns);
+	free(zero);
+
+	if(r != 0)
+		return r;
+
+	x = bo->b;
+	y = bo->b+1;
+	for(i = 0; i < rows; i++, x += pp->columns, y += n)
+		memmove(x, y, pp->columns);
+	bo->sz -= rows;
+
+	return r;
+}
+
+int
+flopenpredict(Filter *f, Object *o)
+{
+	Object *parms;
+	PredictParms *pp;
+	int predictor, columns;
+
+	parms = dictget(o, "DecodeParms");
+	predictor = dictint(parms, "Predictor");
+	columns = dictint(parms, "Columns");
+	if((predictor >= 2 && predictor < 10) || predictor >= 15){
+		werrstr("unsupported flate predictor %d", predictor);
+		return -1;
+	}
+	if(predictor >= 10 && predictor <= 15 && columns < 1){
+		werrstr("invalid columns %d for predictor %d", columns, predictor);
+		return -1;
+	}
+
+	if((pp = malloc(sizeof(*pp))) == nil)
+		return -1;
+	pp->predictor = predictor;
+	pp->columns = columns;
+	f->aux = pp;
+
+	return 0;
+}
+
+void
+flclosepredict(Filter *f)
+{
+	free(f->aux);
+}