/* * jbgtopbm85 - JBIG to Portable Bitmap converter (T.85 version) * * Markus Kuhn - http://www.cl.cam.ac.uk/~mgk25/jbigkit/ */ #include #include #include #include #include "jbig85.h" char *progname; /* global pointer to argv[0] */ unsigned long y_0; fpos_t ypos; int ypos_error = 1; unsigned long ymax = 0; /* * Print usage message and abort */ static void usage(void) { fprintf(stderr, "JBIGtoPBM converter " JBG85_VERSION " (T.85 version) --\n" "reads a bi-level image entity (BIE) as input file\n\n" "usage: %s [ | - []]\n\n", progname); fprintf(stderr, "options:\n\n" " -x number\tmaximum number of pixels per line for which memory\n" "\t\tis allocated (default: 8192)\n" " -y number\tinterrupt decoder after this number of lines\n" " -B number\tinput buffer size\n\n"); exit(1); } /* * Call-back routine for merged image output */ int line_out(const struct jbg85_dec_state *s, unsigned char *start, size_t len, unsigned long y, void *file) { if (y == 0) { /* prefix first line with PBM header */ fprintf((FILE *) file, "P4\n"); fprintf((FILE *) file, "%10lu\n", jbg85_dec_getwidth(s)); /* store file position of height, so we can update it after NEWLEN */ y_0 = jbg85_dec_getheight(s); ypos_error = fgetpos((FILE *) file, &ypos); fprintf((FILE *) file, "%10lu\n", y_0); /* pad number to 10 bytes */ } fwrite(start, len, 1, (FILE *) file); return y == ymax - 1; } int main (int argc, char **argv) { FILE *fin = stdin, *fout = stdout; const char *fnin = NULL, *fnout = NULL; int i, j, result; int all_args = 0, files = 0; struct jbg85_dec_state s; unsigned char *inbuf, *outbuf; size_t inbuflen = 8192, outbuflen, len, cnt, cnt2; unsigned long xmax = 8192; size_t bytes_read = 0; /* parse command line arguments */ progname = argv[0]; for (i = 1; i < argc; i++) { if (!all_args && argv[i][0] == '-') if (argv[i][1] == 0) { if (files++) usage(); } else for (j = 1; j > 0 && argv[i][j]; j++) switch(argv[i][j]) { case '-' : all_args = 1; break; case 'x': if (++i >= argc) usage(); j = -1; xmax = atol(argv[i]); break; case 'y': if (++i >= argc) usage(); j = -1; ymax = atol(argv[i]); break; case 'B': if (++i >= argc) usage(); j = -1; inbuflen = atol(argv[i]); if (inbuflen < 1) usage(); break; default: usage(); } else switch (files++) { case 0: fnin = argv[i]; break; case 1: fnout = argv[i]; break; default: usage(); } } inbuf = (unsigned char *) malloc(inbuflen); outbuflen = ((xmax >> 3) + !!(xmax & 7)) * 3; outbuf = (unsigned char *) malloc(outbuflen); if (!inbuf || !outbuf) { printf("Sorry, not enough memory available!\n"); exit(1); } if (fnin) { fin = fopen(fnin, "rb"); if (!fin) { fprintf(stderr, "Can't open input file '%s", fnin); perror("'"); exit(1); } } else fnin = ""; if (fnout) { fout = fopen(fnout, "wb"); if (!fout) { fprintf(stderr, "Can't open input file '%s", fnout); perror("'"); exit(1); } } else fnout = ""; /* send input file to decoder */ jbg85_dec_init(&s, outbuf, outbuflen, line_out, fout); result = JBG_EAGAIN; while ((len = fread(inbuf, 1, inbuflen, fin))) { result = jbg85_dec_in(&s, inbuf, len, &cnt); bytes_read += cnt; while (result == JBG_EOK_INTR) { /* demonstrate decoder interrupt at given line number */ printf("Decoding interrupted after %lu lines and %lu BIE bytes " "... continuing ...\n", s.y, (unsigned long) bytes_read); /* and now continue decoding */ result = jbg85_dec_in(&s, inbuf + cnt, len - cnt, &cnt2); bytes_read += cnt2; cnt += cnt2; } if (result != JBG_EAGAIN) break; } if (ferror(fin)) { fprintf(stderr, "Problem while reading input file '%s", fnin); perror("'"); if (fout != stdout) { fclose(fout); remove(fnout); } exit(1); } if (result == JBG_EAGAIN || result == JBG_EOK_INTR) { /* signal end-of-BIE explicitely */ result = jbg85_dec_end(&s); while (result == JBG_EOK_INTR) { /* demonstrate decoder interrupt at given line number */ printf("Decoding interrupted after %lu lines and %lu BIE bytes " "... continuing ...\n", s.y, (unsigned long) bytes_read); result = jbg85_dec_end(&s); } } if (result != JBG_EOK) { fprintf(stderr, "Problem with input file '%s': %s\n" "(error code 0x%02x, %lu = 0x%04lx BIE bytes " "and %lu pixel rows processed)\n", fnin, jbg85_strerror(result), result, (unsigned long) bytes_read, (unsigned long) bytes_read, s.y); if (fout != stdout) { fclose(fout); /*remove(fnout);*/ } exit(1); } /* do we have to update the image height in the PBM header? */ if (!ypos_error && y_0 != jbg85_dec_getheight(&s)) { if (fsetpos(fout, &ypos) == 0) { fprintf(fout, "%10lu", jbg85_dec_getheight(&s)); /* pad to 10 bytes */ } else { fprintf(stderr, "Problem while updating height in output file '%s", fnout); perror("'"); exit(1); } } /* check for file errors and close fout */ if (ferror(fout) || fclose(fout)) { fprintf(stderr, "Problem while writing output file '%s", fnout); perror("'"); exit(1); } return 0; }