/* libpbm1.c - pbm utility library part 1 ** ** Copyright (C) 1988 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. */ /* See pmfileio.c for the complicated explanation of this 32/64 bit file offset stuff. */ #define _FILE_OFFSET_BITS 64 #define _LARGE_FILES #include #include "pm_c_util.h" #include "mallocvar.h" #include "shhopt.h" #include "pbm.h" bit * pbm_allocrow(unsigned int const cols) { bit * bitrow; MALLOCARRAY(bitrow, cols); if (bitrow == NULL) pm_error("Unable to allocate space for a %u-column bit row", cols); return bitrow; } void pbm_init(int * const argcP, char ** const argv) { pm_proginit(argcP, (const char **)argv); } void pbm_nextimage(FILE *file, int * const eofP) { pm_nextimage(file, eofP); } void pbm_check(FILE * file, const enum pm_check_type check_type, const int format, const int cols, const int rows, enum pm_check_code * const retval_p) { if (rows < 0) pm_error("Invalid number of rows passed to pbm_check(): %d", rows); if (cols < 0) pm_error("Invalid number of columns passed to pbm_check(): %d", cols); if (check_type != PM_CHECK_BASIC) { if (retval_p) *retval_p = PM_CHECK_UNKNOWN_TYPE; } else if (format != RPBM_FORMAT) { if (retval_p) *retval_p = PM_CHECK_UNCHECKABLE; } else { pm_filepos const bytes_per_row = (cols+7)/8; pm_filepos const need_raster_size = rows * bytes_per_row; #ifdef LARGEFILEDEBUG pm_message("pm_filepos passed to pm_check() is %u bytes", sizeof(pm_filepos)); #endif pm_check(file, check_type, need_raster_size, retval_p); } } static unsigned int bitpop8(unsigned char const x) { /*---------------------------------------------------------------------------- Return the number of 1 bits in 'x' -----------------------------------------------------------------------------*/ static unsigned int const p[256] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 }; return p[x]; } static int bitpop(const unsigned char * const packedRow, unsigned int const cols) { /*---------------------------------------------------------------------------- Return the number of 1 bits in 'packedRow'. -----------------------------------------------------------------------------*/ unsigned int const colByteCnt = pbm_packed_bytes(cols); unsigned int const fullByteCnt = cols/8; unsigned int i; unsigned int sum; sum = 0; /* initial value */ for (i = 0; i < fullByteCnt; ++i) sum += bitpop8(packedRow[i]); if (colByteCnt > fullByteCnt) sum += bitpop8(packedRow[i] >> (8-cols%8)); return sum; } bit pbm_backgroundbitrow(unsigned const char * const packedBits, unsigned int const cols, unsigned int const offset) { /*---------------------------------------------------------------------------- PBM version of pnm_backgroundxelrow() with additional offset parameter. When offset == 0, produces the same return value as does pnm_backgroundxelrow(promoted_bitrow, cols, ...) -----------------------------------------------------------------------------*/ const unsigned char * const row = &packedBits[offset/8]; unsigned int const rs = offset % 8; unsigned int const last = pbm_packed_bytes(cols + rs) - 1; unsigned int retval; unsigned int firstbit, lastbit; unsigned int totalBitpop, headBitpop; firstbit = (row[0] >> (7-rs)) & 0x01; lastbit = (row[last] >> (7- (cols+rs-1)%8)) & 0x01; if (firstbit == lastbit) retval = firstbit; else { totalBitpop = bitpop(row, cols + rs); headBitpop = (rs == 0) ? 0 : bitpop(row, rs); if (totalBitpop - headBitpop >= cols/2) retval = PBM_BLACK; else retval = PBM_WHITE; } return retval; }