/* mgrtopbm.c - read a MGR bitmap and produce a PBM image. Copyright information is at end of file. You can find MGR and some MGR format test images at ftp://sunsite.unc.edu/pub/Linux/apps/MGR/!INDEX.html */ #include #include #include "pbm.h" #include "mgr.h" static void interpHdrWidth(struct b_header const head, unsigned int * const colsP) { if (head.h_wide < ' ' || head.l_wide < ' ') pm_error("Invalid width field in MGR header"); else { unsigned int const maxDimension = 4095; unsigned int const cols = (((int)head.h_wide - ' ') << 6) + ((int)head.l_wide - ' '); if (cols == 0 || cols > maxDimension) pm_error("Invalid width value (%u) in MGR header", cols); else *colsP = cols; } } static void interpHdrHeight(struct b_header const head, unsigned int * const rowsP) { if (head.h_high < ' ' || head.l_high < ' ') pm_error("Invalid height field in MGR header"); else { unsigned int const maxDimension = 4095; unsigned int const rows = (((int)head.h_high - ' ') << 6) + ((int)head.l_high - ' '); if (rows == 0 || rows > maxDimension) pm_error("Invalid height value (%u) in MGR header", rows); else *rowsP = rows; } } static void readMgrHeader(FILE * const ifP, unsigned int * const colsP, unsigned int * const rowsP, unsigned int * const depthP, unsigned int * const padrightP ) { struct b_header head; unsigned int pad; size_t bytesRead; bytesRead = fread(&head, sizeof(struct old_b_header), 1, ifP); if (bytesRead != 1) pm_error("Unable to read 1st byte of file. " "fread() returns errno %d (%s)", errno, strerror(errno)); if (head.magic[0] == 'y' && head.magic[1] == 'z') { /* new style bitmap */ size_t bytesRead; bytesRead = fread(&head.depth, sizeof(head) - sizeof(struct old_b_header), 1, ifP); if (bytesRead != 1 ) pm_error("Unable to read header after 1st byte. " "fread() returns errno %d (%s)", errno, strerror(errno)); *depthP = (int) head.depth - ' '; pad = 8; } else if (head.magic[0] == 'x' && head.magic[1] == 'z') { /* old style bitmap with 32-bit padding */ *depthP = 1; pad = 32; } else if (head.magic[0] == 'z' && head.magic[1] == 'z') { /* old style bitmap with 16-bit padding */ *depthP = 1; pad = 16; } else if (head.magic[0] == 'z' && head.magic[1] == 'y') { /* old style 8-bit pixmap with 16-bit padding */ *depthP = 8; pad = 16; } else { pm_error("bad magic chars in MGR file: '%c%c'", head.magic[0], head.magic[1] ); pad = 0; /* should never reach here */ } interpHdrWidth (head, colsP); interpHdrHeight(head, rowsP); *padrightP = ((*colsP + pad - 1) / pad) * pad - *colsP; } int main(int argc, char * argv[]) { FILE * ifP; unsigned char * bitrow; unsigned int rows, cols, depth; unsigned int padright; unsigned int row; unsigned int itemCount; const char * inputFileName; pbm_init(&argc, argv); if (argc-1 > 1) pm_error("Too many arguments (%u). " "Only argument is optional input file", argc-1); if (argc-1 == 1) inputFileName = argv[1]; else inputFileName = "-"; ifP = pm_openr(inputFileName); readMgrHeader(ifP, &cols, &rows, &depth, &padright); if (depth != 1) pm_error("MGR file has depth of %u, must be 1", depth); pbm_writepbminit(stdout, cols, rows, 0); bitrow = pbm_allocrow_packed(cols + padright); itemCount = (cols + padright ) / 8; for (row = 0; row < rows; ++row) { /* The raster formats are nearly identical. MGR may have rows padded to 16 or 32 bit boundaries. */ size_t bytesRead; bytesRead = fread(bitrow, 1, itemCount, ifP); if (bytesRead < itemCount) pm_error("fread() failed to read mgr bitmap data"); pbm_writepbmrow_packed(stdout, bitrow, cols, 0); } pm_close(ifP); pm_close(stdout); return 0; } /* 2006.10 (afu) Changed bitrow from plain to raw, read function from getc() to fread(), write function from pbm_writepbmrow() to pbm_writepbmrow_packed(). Retired bitwise transformation functions. NOT tested for old-style format files. Only one zz file in mgrsrc-0.69 . */ /* ** Copyright (C) 1989 by Jef Poskanzer. ** ** Permission to use, copy, modify, and distribute this software and its ** documentation for any purpose and without fee is hereby granted, provided ** that the above copyright notice appear in all copies and that both that ** copyright notice and this permission notice appear in supporting ** documentation. This software is provided "as is" without express or ** implied warranty. */