From 966ca9faa3ea0ae97a081e933852cb6839bfd38c Mon Sep 17 00:00:00 2001 From: Manolo Gouy Date: Sun, 1 Mar 2015 12:11:52 +0000 Subject: PostScript output of images: use now RunLengthEncode followed by ASCII85Encode filters. This is what Mac OS X does for its PostScript output, so there must be some good in that. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@10597 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 --- src/ps_image.cxx | 127 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 102 insertions(+), 25 deletions(-) (limited to 'src/ps_image.cxx') diff --git a/src/ps_image.cxx b/src/ps_image.cxx index 02dded8bf..0b69212da 100644 --- a/src/ps_image.cxx +++ b/src/ps_image.cxx @@ -50,7 +50,7 @@ static struct85 *prepare85(FILE *outfile) // prepare to produce ASCII85-encoded return big; } -// encodes 4 input bytes from bytes4 into chars5 array +// ASCII85-encodes 4 input bytes from bytes4 into chars5 array // returns # of output chars static int convert85(const uchar *bytes4, uchar *chars5) { @@ -71,7 +71,7 @@ static int convert85(const uchar *bytes4, uchar *chars5) } -static void write85(const uchar *p, struct85 *big, int len) // sends len input bytes for encoding +static void write85(struct85 *big, const uchar *p, int len) // sends len input bytes for ASCII85 encoding { const uchar *last = p + len; while (p < last) { @@ -108,6 +108,86 @@ static void close85(struct85 *big) // stops ASCII85-encoding after processing r // End of implementation of the /ASCII85Encode PostScript filter // +// +// Implementation of the /RunLengthEncode + /ASCII85Encode PostScript filter +// as described in "PostScript LANGUAGE REFERENCE third edition" p. 142 +// + +struct struct_rle85 { + struct85 *data85; // aux data for ASCII85 encoding + uchar buffer[128]; // holds non-run data + int count; // current buffer length + int run_length; // current length of run +}; + +static struct_rle85 *prepare_rle85(FILE *out) // prepare to produce RLE+ASCII85-encoded output +{ + struct_rle85 *rle = new struct_rle85; + rle->count = 0; + rle->run_length = 0; + rle->data85 = prepare85(out); + return rle; +} + + +static void write_rle85(uchar b, struct_rle85 *rle) // sends one input byte to RLE+ASCII85 encoding +{ + uchar c; + if (rle->run_length > 0) { // if within a run + if (b == rle->buffer[0] && rle->run_length < 128) { // the run can be extended + rle->run_length++; + return; + } else { // output the run + uchar c = (uchar)(257 - rle->run_length); + write85(rle->data85, &c, 1); // the run-length info + write85(rle->data85, rle->buffer, 1); // the byte of the run + rle->run_length = 0; + } + } + if (rle->count >= 2 && b == rle->buffer[rle->count-1] && b == rle->buffer[rle->count-2]) { + // about to begin a run + if (rle->count > 2) { // there is non-run data before the run in the buffer + c = (uchar)(rle->count-2 - 1); + write85(rle->data85, &c, 1); // length of non-run data + write85(rle->data85, rle->buffer, rle->count-2); // non-run data + } + rle->run_length = 3; + rle->buffer[0] = b; + rle->count = 0; + return; + } + if (rle->count >= 128) { // the non-run buffer is full, output it + c = (uchar)(rle->count - 1); + write85(rle->data85, &c, 1); // length of non-run data + write85(rle->data85, rle->buffer, rle->count); // non-run data + rle->count = 0; + } + rle->buffer[rle->count++] = b; // add byte to end of non-run buffer +} + + +static void close_rle85(struct_rle85 *rle) // stop doing RLE+ASCII85 encoding +{ + uchar c; + if (rle->run_length > 0) { // if within a run, output it + c = (uchar)(257 - rle->run_length); + write85(rle->data85, &c, 1); + write85(rle->data85, rle->buffer, 1); + } else if (rle->count) { // output the non-run buffer, if not empty + c = (uchar)(rle->count - 1); + write85(rle->data85, &c, 1); + write85(rle->data85, rle->buffer, rle->count); + } + c = (uchar)128; + write85(rle->data85, &c, 1); // output EOD mark + close85(rle->data85); // close ASCII85 encoding process + delete rle; +} + +// +// End of implementation of the /RunLengthEncode + /ASCII85Encode PostScript filter +// + int Fl_PostScript_Graphics_Driver::alpha_mask(const uchar * data, int w, int h, int D, int LD){ @@ -328,37 +408,35 @@ void Fl_PostScript_Graphics_Driver::draw_image(Fl_Draw_Image_Cb call, void *data int LD=iw*D; uchar *rgbdata=new uchar[LD]; uchar *curmask=mask; - uchar line[3]; - struct85 *big = prepare85(output); + struct_rle85 *big = prepare_rle85(output); if (level2_mask) { for (j = ih - 1; j >= 0; j--) { // output full image data call(data, 0, j, iw, rgbdata); uchar *curdata = rgbdata; for (i=0 ; i= 0; j--) { // output mask data curmask = mask + j * (my/ih) * ((mx+7)/8); for (k=0; k < my/ih; k++) { for (i=0; i < ((mx+7)/8); i++) { - line[0] = swap_byte(*curmask); write85(line, big, 1); + write_rle85(swap_byte(*curmask), big); curmask++; } } } - close85(big); } else { for (j=0; j 2) { // InterleaveType 2 mask data for (k=0; k2){ // InterleaveType 2 mask data for (k=0; k