static void writeCroppedPBM(FILE * const ifP, unsigned int const cols, unsigned int const rows, int const format, cropSet const crop, xel const backgroundColor, FILE * const ofP) { /* See comments for writeCroppedNonPBM(), which uses identical logic flow. Uses pbm functions instead of general pnm functions. */ unsigned int const foregroundCols = cols - crop.op[LEFT].removeSize - crop.op[RIGHT].removeSize; unsigned int const outputCols = foregroundCols + crop.op[LEFT].padSize + crop.op[RIGHT].padSize; unsigned int const foregroundRows = rows - crop.op[TOP].removeSize - crop.op[BOTTOM].removeSize; unsigned int const outputRows = foregroundRows + crop.op[TOP].padSize + crop.op[BOTTOM].padSize; unsigned int const foregroundLeft = MAX(crop.op[LEFT].removeSize, crop.op[LEFT].padSize); unsigned int const foregroundRight = foregroundLeft + foregroundCols; unsigned int const allocCols = foregroundRight + MAX(crop.op[RIGHT].removeSize, crop.op[RIGHT].padSize); unsigned int const backgroundBlackWhite = PNM_EQUAL(backgroundColor, pnm_whitexel(1, PBM_TYPE)) ? 0: 1; unsigned int const readOffset = foregroundLeft - crop.op[LEFT].removeSize; unsigned int const writeOffset = foregroundLeft - crop.op[LEFT].padSize; unsigned int const lastWriteChar = writeOffset/8 + (outputCols-1)/8; unsigned char * bitrow; unsigned int i; pbm_writepbminit(ofP, outputCols, outputRows, 0); bitrow = pbm_allocrow_packed(allocCols); readOffBorderPbm(crop.op[TOP].removeSize, ifP, cols, format); outputNewBorderPbm(crop.op[TOP].padSize, outputCols, backgroundBlackWhite, ofP); /* Prepare padding: left and/or right */ fillRowPBM(bitrow, allocCols, backgroundBlackWhite); /* Read and output foreground rows */ for (i = 0; i < foregroundRows; ++i) { /* Read foreground pixels */ pbm_readpbmrow_bitoffset(ifP, bitrow, cols, format, readOffset); pbm_writepbmrow_bitoffset(ofP, bitrow, outputCols, format, writeOffset); /* If there is right-side padding, repair the write buffer distorted by pbm_writepbmrow_bitoffset() (No need to mend any left-side padding) */ if (crop.op[RIGHT].padSize > 0) bitrow[lastWriteChar] = backgroundBlackWhite * 0xff; } readOffBorderPbm(crop.op[BOTTOM].removeSize, ifP, cols, format); outputNewBorderPbm(crop.op[BOTTOM].padSize, outputCols, backgroundBlackWhite, ofP); pbm_freerow_packed(bitrow); }
static void extractRowsPBM(const struct pam * const inpamP, const struct pam * const outpamP, int const leftcol, int const rightcol, int const toprow, int const bottomrow) { unsigned char * bitrow; int readOffset, writeOffset; int row; unsigned int totalWidth; assert(leftcol <= rightcol); assert(toprow <= bottomrow); if (leftcol > 0) { totalWidth = MAX(rightcol+1, inpamP->width) + 7; if (totalWidth > INT_MAX) /* Prevent overflows in pbm_allocrow_packed() */ pm_error("Specified right edge is too far " "from the right end of input image"); readOffset = 0; writeOffset = leftcol; } else { totalWidth = -leftcol + MAX(rightcol+1, inpamP->width); if (totalWidth > INT_MAX) pm_error("Specified left/right edge is too far " "from the left/right end of input image"); readOffset = -leftcol; writeOffset = 0; } bitrow = pbm_allocrow_packed(totalWidth); if (toprow < 0 || leftcol < 0 || rightcol >= inpamP->width){ makeBlackPBMRow(bitrow, totalWidth); if (toprow < 0) { int row; for (row=0; row < 0 - toprow; ++row) pbm_writepbmrow_packed(outpamP->file, bitrow, outpamP->width, 0); } } for (row = 0; row < inpamP->height; ++row){ if (row >= toprow && row <= bottomrow) { pbm_readpbmrow_bitoffset(inpamP->file, bitrow, inpamP->width, inpamP->format, readOffset); pbm_writepbmrow_bitoffset(outpamP->file, bitrow, outpamP->width, 0, writeOffset); if (rightcol >= inpamP->width) /* repair right padding */ bitrow[writeOffset/8 + pbm_packed_bytes(outpamP->width) - 1] = 0xff * PBM_BLACK; } else pnm_readpamrow(inpamP, NULL); /* read and discard */ } if (bottomrow - (inpamP->height-1) > 0) { int row; makeBlackPBMRow(bitrow, outpamP->width); for (row = 0; row < bottomrow - (inpamP->height-1); ++row) pbm_writepbmrow_packed(outpamP->file, bitrow, outpamP->width, 0); } pbm_freerow_packed(bitrow); }