diff --git a/pdf.c b/pdf.c
index 8c08493c783bce59e6916a4b04952badd267c0eb..d169604736cd618e38d2b661d6c849aae9cf9d4c 100644
--- a/pdf.c
+++ b/pdf.c
@@ -632,6 +632,32 @@ act_dict_(const HParseResult *p, void *env)
 
 #define act_array_ h_act_flatten
 
+HParsedToken *
+act_longlength(const HParseResult *p, void *env)
+{
+	uint8_t length = H_CAST_UINT(p->ast);
+	uint8_t finallength = 257-length;
+
+	return H_MAKE_UINT(finallength);
+}
+
+HParsedToken *
+act_longrun(const HParseResult *p, void *env)
+{
+	HCountedArray *seq = H_CAST_SEQ(p->ast);
+	HParsedToken **elements = h_seq_elements(p->ast);
+	HParsedToken *res = H_MAKE_SEQ();
+
+	uint8_t length = H_CAST_UINT(elements[0]);
+	uint8_t data = H_CAST_UINT(elements[1]);
+
+	for (size_t len = 0; len < length; ++len)
+	{
+		h_seq_snoc(res, H_MAKE_UINT(data));
+	}
+
+	return res;
+}
 
 /*
  * input grammar
@@ -645,10 +671,30 @@ HParser *p_objdef;
 HParser *p_a85string;
 HParser *p_ahexstream;
 
+HParser *p_rldstring;
+
 /* continuations for h_bind() */
 HParser *kstream(HAllocator *, const HParsedToken *, void *);
 HParser *kxstream(HAllocator *, const HParsedToken *, void *);
 
+void
+init_runlengthdecode_parser(struct Env *aux)
+{
+	H_RULE(rldeod, h_ch(0x80));
+	H_ARULE(longlength, h_ch_range(0x81, 0xFF));
+	H_RULE(shortlength, h_ch_range(0x1, 0x7F));
+
+	H_RULE(shortdata, h_uint8());
+	H_RULE(longdata, h_uint8());
+
+	H_RULE(shortrun, h_length_value(shortlength, shortdata));
+	H_ARULE(longrun, SEQ(longlength, longdata));
+
+	H_RULE(rldstring, SEQ(CHX(shortrun, longrun), IGN(rldeod)));
+
+	p_rldstring = rldstring;
+}
+
 void
 init_parser(struct Env *aux)
 {
@@ -928,6 +974,8 @@ init_parser(struct Env *aux)
 	H_RULE(hs_end, CHX(hdigitpair, ahextruncated));
 	H_RULE(hexstream, SEQ(h_many(hdigitpair), hs_end));
 
+	init_runlengthdecode_parser(aux);
+
 
 	/* global parser variables */
 	p_pdf = pdf;
@@ -1308,6 +1356,21 @@ FlateDecode(const Dict *parms, HBytes b, HParser *p)
 	return res;
 }
 
+HParseResult *
+RunLengthDecode(const Dict *parms, HBytes b, HParser *p)
+{
+	HParseResult *res;
+
+	res = h_parse(p_rldstring, b.token, b.len);
+	if(!res)
+	{
+		fprintf(stderr, "parse error in RunLengthDecode filter\n");
+		return NULL;
+	}
+
+	return res;
+}
+
 /*
  * Decodes ASCII hexadecimal data into binary data.
  * parms should be empty, because the filter has no parameters
@@ -1374,6 +1437,8 @@ decode_stream(const Dict *d, HBytes b, HParser *p)
 		filter = ASCIIHexDecode;
 	else if (bytes_eq(v->bytes, "ASCII85Decode"))
 		filter = ASCII85Decode;
+	else if (bytes_eq(v->bytes, "RunLengthDecode"))
+		filter = RunLengthDecode;
 	else
 		return NULL;		/* filter not supported */