/* * This was adapted for Netpbm from bmpesoe.c in Dirk Krause's Bmeps package * by Bryan Henderson on 2005.01.05. * * Differences: * - doesn't require Bmeps configuration stuff (bmepsco.h) * - doesn't include pngeps.h * - doesn't have test scaffold code * - a few compiler warnings fixed * * Copyright (C) 2000 - Dirk Krause * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * In this package the copy of the GNU Library General Public License * is placed in file COPYING. */ #include "bmepsoe.h" #define RL_RUNLENGTH(i) (257 - (i)) #define RL_STRINGLENGTH(i) ((i) - 1) #define RL_MAXLENGTH (127) #define FINALOUTPUT(c) fputc((c),o->out) void oe_init(Output_Encoder *o, FILE *out, int mode, int rate, int *buf, Bytef *flib, size_t flis, Bytef *flob, size_t flos ) { o->out = out; o->mode = mode; o->textpos = 0; o->a85_value = 0UL; o->a85_consumed = 0; o->a85_0 = 1UL; o->a85_1 = 85UL; o->a85_2 = 85UL * 85UL; o->a85_3 = 85UL * o->a85_2; o->a85_4 = 85UL * o->a85_3; o->rl_lastbyte = 0; o->rl_buffer = buf; o->rl_bufused = 0; o->rl_state = 0; o->bit_value = 0; o->bit_consumed = 0; o->flate_rate = rate; if(o->flate_rate < 0) { o->mode &= (~OE_FLATE); } if(o->flate_rate > 9) { o->flate_rate = 9; } if((o->mode & OE_FLATE) && flib && flis && flob && flos) { (o->flate_stream).zfree = (free_func)0; (o->flate_stream).zalloc = (alloc_func)0; (o->flate_stream).opaque = (voidpf)0; if(deflateInit((&(o->flate_stream)),o->flate_rate) != Z_OK) { o->mode &= (~OE_FLATE); } } o->fl_i_buffer = flib; o->fl_o_buffer = flob; o->fl_i_size = flis; o->fl_o_size = flos; o->fl_i_used = 0; } static char hexdigits[] = { "0123456789ABCDEF" }; static void asciihex_add(Output_Encoder *o, int b) { FINALOUTPUT(hexdigits[(b/16)]) ; FINALOUTPUT(hexdigits[(b%16)]) ; o->textpos = o->textpos + 2; if(o->textpos >= 64) { FINALOUTPUT('\n') ; o->textpos = 0; } } static void asciihex_flush(Output_Encoder *o) { if(o->textpos > 0) { FINALOUTPUT('\n') ; o->textpos = 0; } } static char ascii85_char(unsigned long x) { unsigned u; int i; char back; back = (char)0; u = (unsigned)x; i = (int)u; i += 33; back = (char)i; return back; } static void ascii85_output(Output_Encoder * const o) { unsigned long value; value = o->a85_value; /* initial value */ if (value == 0 && o->a85_consumed == 4) { FINALOUTPUT('z'); ++o->textpos; } else { unsigned int i; unsigned int j; char buffer[6]; buffer[0] = ascii85_char(value / (o->a85_4)); value = value % (o->a85_4); buffer[1] = ascii85_char(value / (o->a85_3)); value = value % (o->a85_3); buffer[2] = ascii85_char(value / (o->a85_2)); value = value % (o->a85_2); buffer[3] = ascii85_char(value / (o->a85_1)); value = value % (o->a85_1); buffer[4] = ascii85_char(value); buffer[5] = '\0'; i = o->a85_consumed + 1; o->textpos += i; for (j = 0; j < i; ++j) FINALOUTPUT(buffer[j]); } if (o->textpos >= 64) { FINALOUTPUT('\n'); o->textpos = 0; } } static void ascii85_add(Output_Encoder *o, int b) { unsigned u; unsigned long ul; u = (unsigned)b; ul = (unsigned long)u; o->a85_value = 256UL * (o->a85_value) + ul; o->a85_consumed = o->a85_consumed + 1; if(o->a85_consumed >= 4) { ascii85_output(o); o->a85_value = 0UL; o->a85_consumed = 0; } } static void ascii85_flush(Output_Encoder *o) { int i; if(o->a85_consumed > 0) { i = o->a85_consumed; while(i < 4) { o->a85_value = 256UL * o->a85_value; i++; } ascii85_output(o); o->a85_value = 0UL; o->a85_consumed = 0; } if(o->textpos > 0) { FINALOUTPUT('\n') ; o->textpos = 0; } } static void after_flate_add(Output_Encoder *o, int b) { if(o->mode & OE_ASC85) { ascii85_add(o,b); } else { asciihex_add(o,b); } } static void do_flate_flush(Output_Encoder * const oP, int const final) { Bytef *iptr, *optr, *xptr; unsigned long is; unsigned long os; unsigned long xs; int err; int mustContinue; iptr = oP->fl_i_buffer; optr = oP->fl_o_buffer; is = oP->fl_i_size; os = oP->fl_o_size; if (iptr && optr && is && os) { is = oP->fl_i_used; if (is || final) { oP->flate_stream.next_in = iptr; oP->flate_stream.avail_in = is; if (final) { mustContinue = 1; while (mustContinue) { oP->flate_stream.next_out = optr; oP->flate_stream.avail_out = os; mustContinue = 0; err = deflate(&oP->flate_stream, Z_FINISH); switch (err) { case Z_STREAM_END: { xptr = optr; xs = os - (oP->flate_stream.avail_out); while (xs--) { after_flate_add(oP, *(xptr++)); } } break; case Z_OK : { mustContinue = 1; xptr = optr; xs = os - (oP->flate_stream.avail_out); while (xs--) { after_flate_add(oP, *(xptr++)); } } break; default : { } break; } } } else { mustContinue = 1; while (mustContinue) { mustContinue = 0; oP->flate_stream.avail_out = os; oP->flate_stream.next_out = optr; err = deflate(&oP->flate_stream, 0); switch (err) { case Z_OK: { if (oP->flate_stream.avail_in) { mustContinue = 1; } xptr = optr; xs = os - (oP->flate_stream.avail_out); while (xs--) { after_flate_add(oP, *(xptr++)); } } break; default : { } break; } } } } } } static void flate_add(Output_Encoder *o, int b) { Byte bt; Bytef *btptr; btptr = o->fl_i_buffer; if(btptr) { bt = (Byte)b; btptr[(o->fl_i_used)] = bt; o->fl_i_used += 1UL; if(o->fl_i_used >= o->fl_i_size) { do_flate_flush(o, 0); o->fl_i_used = 0UL; } } } static void after_flate_flush(Output_Encoder *o) { if(o->mode & OE_ASC85) { ascii85_flush(o); } else { asciihex_flush(o); } } static void flate_flush(Output_Encoder *o) { do_flate_flush(o,1); deflateEnd(&(o->flate_stream)); after_flate_flush(o); } static void after_rl_add(Output_Encoder *o, int b) { if(o->mode & OE_FLATE) { flate_add(o,b); } else { after_flate_add(o,b); } } static void rl_add(Output_Encoder *o, int b) { int lgt, i; int *buffer; /* ##### */ buffer = o->rl_buffer; lgt = o->rl_bufused; if(buffer) { if(lgt > 0) { if(o->rl_lastbyte == b) { switch(o->rl_state) { case 2: { buffer[lgt++] = b; o->rl_bufused = lgt; o->rl_state = 2; o->rl_lastbyte = b; if(lgt >= RL_MAXLENGTH) { after_rl_add(o, RL_RUNLENGTH(lgt)); after_rl_add(o, b); o->rl_bufused = 0; o->rl_state = 0; o->rl_lastbyte = b; } } break; case 1: { buffer[lgt++] = b; o->rl_bufused = lgt; o->rl_state = 2; o->rl_lastbyte = b; lgt = lgt - 3; if(lgt > 0) { after_rl_add(o, RL_STRINGLENGTH(lgt)); for(i = 0; i < lgt; i++) { after_rl_add(o, buffer[i]); } buffer[0] = buffer[1] = buffer[2] = b; o->rl_bufused = 3; o->rl_state = 2; o->rl_lastbyte = b; } } break; default: { buffer[lgt++] = b; o->rl_bufused = lgt; o->rl_state = 1; o->rl_lastbyte = b; if(lgt >= RL_MAXLENGTH) { lgt = lgt - 2; after_rl_add(o, RL_STRINGLENGTH(lgt)); for(i = 0; i < lgt; i++) { after_rl_add(o, buffer[i]); } buffer[0] = buffer[1] = b; o->rl_bufused = 2; o->rl_state = 1; o->rl_lastbyte = b; } } break; } } else { if(o->rl_state == 2) { after_rl_add(o, RL_RUNLENGTH(lgt)); after_rl_add(o, (o->rl_lastbyte)); buffer[0] = b; o->rl_bufused = 1; o->rl_lastbyte = b; o->rl_state = 0; } else { buffer[lgt++] = b; o->rl_bufused = lgt; o->rl_lastbyte = b; if(lgt >= RL_MAXLENGTH) { after_rl_add(o, RL_STRINGLENGTH(lgt)); for(i = 0; i < lgt; i++) { after_rl_add(o, buffer[i]); } o->rl_bufused = 0; } o->rl_state = 0; } } } else { buffer[0] = b; o->rl_bufused = 1; o->rl_lastbyte = b; } o->rl_lastbyte = b; } else { after_rl_add(o,0); after_rl_add(o,b); } } static void after_rl_flush(Output_Encoder *o) { if(o->mode & OE_FLATE) { flate_flush(o); } else { after_flate_flush(o); } } static void rl_flush(Output_Encoder *o) { int lgt; int *buffer; int i; buffer = o->rl_buffer; lgt = o->rl_bufused; if(lgt > 0) { if(o->rl_state == 2) { i = o->rl_lastbyte; after_rl_add(o,RL_RUNLENGTH(lgt)); after_rl_add(o,i); } else { after_rl_add(o,RL_STRINGLENGTH(lgt)); for(i = 0; i < lgt; i++) { after_rl_add(o,buffer[i]); } } } after_rl_flush(o); } static void internal_byte_add(Output_Encoder * const oP, int const b) { if (oP->mode & OE_RL) rl_add(oP, b); else after_rl_add(oP, b); } static void internal_byte_flush(Output_Encoder *o) { if((o->mode) & OE_RL) { rl_flush(o); } else { after_rl_flush(o); } } void oe_bit_add(Output_Encoder * const oP, int const b) { oP->bit_value = 2 * oP->bit_value + (b ? 1 : 0); oP->bit_consumed = oP->bit_consumed + 1; if (oP->bit_consumed >= 8) { oP->bit_consumed = 0; internal_byte_add(oP, oP->bit_value); oP->bit_value = 0; } } void oe_bit_flush(Output_Encoder *o) { if(o->bit_consumed) { int v, i; v = o->bit_value; i = o->bit_consumed; while(i < 8) { i++; v = v * 2; } internal_byte_add(o,v); o->bit_value = 0; o->bit_consumed = 0; } internal_byte_flush(o); } void oe_byte_add(Output_Encoder * const oP, int const b) { if (oP->bit_consumed) { int testval; int i; testval = 128; for (i = 0; i < 8; ++i) { if (b & testval) { oe_bit_add(oP, 1); } else { oe_bit_add(oP, 0); } testval = testval / 2; } } else { internal_byte_add(oP, b); } } void oe_byte_flush(Output_Encoder *o) { oe_bit_flush(o); }