/* jbigtopnm - JBIG to PNM converter This program was derived from jbgtopbm.c in Markus Kuhn's JBIG-KIT package by Bryan Henderson on 2000.05.11 The main difference is that this version uses the Netpbm libraries. */ #include #include #include #include #include "pnm.h" #define BUFSIZE 8192 static void collect_image (unsigned char *data, size_t len, void *image) { static int cursor = 0; int i; for (i = 0; i < len; i++) { ((unsigned char *)image)[cursor++] = data[i]; } } static void write_pnm (FILE *fout, const unsigned char * const image, const int bpp, const int rows, const int cols, const int maxval, const int format) { int row; xel *pnm_row; pnm_writepnminit(fout, cols, rows, maxval, format, 0); pnm_row = pnm_allocrow(cols); for (row = 0; row < rows; row++) { int col; for (col = 0; col < cols; col++) { int j; for (j = 0; j < bpp; j++) PNM_ASSIGN1(pnm_row[col], image[(((row*cols)+col) * bpp) + j]); } pnm_writepnmrow(fout, pnm_row, cols, maxval, format, 0); } pnm_freerow(pnm_row); } static void write_raw_pbm(FILE * const fout, const unsigned char * const binary_image, int const cols, int const rows) { unsigned int const bytes_per_row = pbm_packed_bytes(cols); int row; pbm_writepbminit(fout, cols, rows, 0); for (row = 0; row < rows; ++row) pbm_writepbmrow_packed(fout, &binary_image[row*bytes_per_row], cols, 0); } /* * */ static void diagnose_bie(FILE *f) { unsigned char bih[20]; int len; unsigned long xd, yd, l0; len = fread(bih, 1, 20, f); if (len < 20) { printf("Input file is %d < 20 bytes long and does therefore not " "contain an intact BIE header!\n", len); return; } printf("Decomposition of BIH:\n\n DL = %d\n D = %d\n P = %d\n" " - = %d\n XD = %lu\n YD = %lu\n L0 = %lu\n MX = %d\n" " MY = %d\n", bih[0], bih[1], bih[2], bih[3], xd = ((unsigned long) bih[ 4] << 24) | ((unsigned long)bih[ 5] << 16)| ((unsigned long) bih[ 6] << 8) | ((unsigned long) bih[ 7]), yd = ((unsigned long) bih[ 8] << 24) | ((unsigned long)bih[ 9] << 16)| ((unsigned long) bih[10] << 8) | ((unsigned long) bih[11]), l0 = ((unsigned long) bih[12] << 24) | ((unsigned long)bih[13] << 16)| ((unsigned long) bih[14] << 8) | ((unsigned long) bih[15]), bih[16], bih[17]); printf(" order = %d %s%s%s%s%s\n", bih[18], bih[18] & JBG_HITOLO ? " HITOLO" : "", bih[18] & JBG_SEQ ? " SEQ" : "", bih[18] & JBG_ILEAVE ? " ILEAVE" : "", bih[18] & JBG_SMID ? " SMID" : "", bih[18] & 0xf0 ? " other" : ""); printf(" options = %d %s%s%s%s%s%s%s%s\n", bih[19], bih[19] & JBG_LRLTWO ? " LRLTWO" : "", bih[19] & JBG_VLENGTH ? " VLENGTH" : "", bih[19] & JBG_TPDON ? " TPDON" : "", bih[19] & JBG_TPBON ? " TPBON" : "", bih[19] & JBG_DPON ? " DPON" : "", bih[19] & JBG_DPPRIV ? " DPPRIV" : "", bih[19] & JBG_DPLAST ? " DPLAST" : "", bih[19] & 0x80 ? " other" : ""); printf("\n %lu stripes, %d layers, %d planes\n\n", ((yd >> bih[1]) + ((((1UL << bih[1]) - 1) & xd) != 0) + l0 - 1) / l0, bih[1] - bih[0], bih[2]); return; } int main (int argc, char **argv) { FILE *fin = stdin, *fout = stdout; const char *fnin = "", *fnout = ""; int i, j, result; int all_args = 0, files = 0; struct jbg_dec_state s; char *buffer; unsigned char *p; size_t len, cnt; unsigned long xmax = 4294967295UL, ymax = 4294967295UL; int plane = -1, use_graycode = 1, diagnose = 0; pnm_init(&argc, argv); buffer = malloc(BUFSIZE); if (!buffer) pm_error("Sorry, not enough memory available!"); /* parse command line arguments */ for (i = 1; i < argc; i++) { if (!all_args && argv[i][0] == '-') { if (argv[i][1] == '\0' && files == 0) ++files; else { for (j = 1; j > 0 && argv[i][j]; j++) { switch(tolower(argv[i][j])) { case '-' : all_args = 1; break; case 'b': use_graycode = 0; break; case 'd': diagnose = 1; break; case 'x': if (++i >= argc) pm_error("-x needs a value"); xmax = atol(argv[i]); j = -1; break; case 'y': if (++i >= argc) pm_error("-y needs a value"); ymax = atol(argv[i]); j = -1; break; case 'p': if (++i >= argc) pm_error("-p needs a value"); plane = atoi(argv[i]); j = -1; break; default: pm_error("Unrecognized option: %c", argv[i][j]); } } } } else { switch (files++) { case 0: if (argv[i][0] != '-' || argv[i][1] != '\0') { fnin = argv[i]; fin = fopen(fnin, "rb"); if (!fin) pm_error("Can't open input file '%s'", fnin); } if (diagnose) { diagnose_bie(fin); exit(0); } break; case 1: fnout = argv[i]; fout = fopen(fnout, "wb"); if (!fout) pm_error("Can't open output file '%s'", fnout); break; default: pm_error("Too many non-option arguments"); } } } /* send input file to decoder */ jbg_dec_init(&s); jbg_dec_maxsize(&s, xmax, ymax); result = JBG_EAGAIN; do { len = fread(buffer, 1, BUFSIZE, fin); if (!len) break; cnt = 0; p = (unsigned char *) buffer; while (len > 0 && (result == JBG_EAGAIN || result == JBG_EOK)) { result = jbg_dec_in(&s, p, len, &cnt); p += cnt; len -= cnt; } } while (result == JBG_EAGAIN || result == JBG_EOK); if (ferror(fin)) pm_error("Problem while reading input file '%s", fnin); if (result != JBG_EOK && result != JBG_EOK_INTR) pm_error("Problem with input file '%s': %s\n", fnin, jbg_strerror(result)); if (plane >= 0 && jbg_dec_getplanes(&s) <= plane) pm_error("Image has only %d planes!\n", jbg_dec_getplanes(&s)); { /* Write it out */ int rows, cols; int maxval; int bpp; int plane_to_write; cols = jbg_dec_getwidth(&s); rows = jbg_dec_getheight(&s); maxval = pm_bitstomaxval(jbg_dec_getplanes(&s)); bpp = (jbg_dec_getplanes(&s)+7)/8; if (jbg_dec_getplanes(&s) == 1) plane_to_write = 0; else plane_to_write = plane; if (plane_to_write >= 0) { /* Write just one plane */ unsigned char * binary_image; pm_message("WRITING PBM FILE"); binary_image=jbg_dec_getimage(&s, plane_to_write); write_raw_pbm(fout, binary_image, cols, rows); } else { unsigned char *image; pm_message("WRITING PGM FILE"); /* Write out all the planes */ /* What jbig.doc doesn't tell you is that jbg_dec_merge_planes delivers the image in chunks, in consecutive calls to the data-out callback function. And a row can span two chunks. */ image = malloc(cols*rows*bpp); jbg_dec_merge_planes(&s, use_graycode, collect_image, image); write_pnm(fout, image, bpp, rows, cols, maxval, PGM_TYPE); free(image); } } pm_close(fout); jbg_dec_free(&s); return 0; }