|
Packit |
78deda |
/* pnmpaste.c - paste a rectangle into a PNM image
|
|
Packit |
78deda |
**
|
|
Packit |
78deda |
** Copyright (C) 1989 by Jef Poskanzer.
|
|
Packit |
78deda |
**
|
|
Packit |
78deda |
** Permission to use, copy, modify, and distribute this software and its
|
|
Packit |
78deda |
** documentation for any purpose and without fee is hereby granted, provided
|
|
Packit |
78deda |
** that the above copyright notice appear in all copies and that both that
|
|
Packit |
78deda |
** copyright notice and this permission notice appear in supporting
|
|
Packit |
78deda |
** documentation. This software is provided "as is" without express or
|
|
Packit |
78deda |
** implied warranty.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#include <assert.h>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#include "pm_c_util.h"
|
|
Packit |
78deda |
#include "mallocvar.h"
|
|
Packit |
78deda |
#include "nstring.h"
|
|
Packit |
78deda |
#include "shhopt.h"
|
|
Packit |
78deda |
#include "pnm.h"
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
enum boolOp {REPLACE, AND, OR, XOR /*, NAND, NOR, NXOR */ };
|
|
Packit |
78deda |
|
|
Packit |
78deda |
struct CmdlineInfo {
|
|
Packit |
78deda |
/* All the information the user supplied in the command line,
|
|
Packit |
78deda |
in a form easy for the program to use.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
const char * baseFilename;
|
|
Packit |
78deda |
const char * insetFilename;
|
|
Packit |
78deda |
int insertCol; /* Negative means from right edge */
|
|
Packit |
78deda |
int insertRow; /* Negative means from bottom edge */
|
|
Packit |
78deda |
enum boolOp operation;
|
|
Packit |
78deda |
};
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
parseCommandLine(int argc, const char ** argv,
|
|
Packit |
78deda |
struct CmdlineInfo * const cmdlineP) {
|
|
Packit |
78deda |
/*----------------------------------------------------------------------------
|
|
Packit |
78deda |
Note that the file spec array we return is stored in the storage that
|
|
Packit |
78deda |
was passed to us as the argv array.
|
|
Packit |
78deda |
-----------------------------------------------------------------------------*/
|
|
Packit |
78deda |
optEntry *option_def;
|
|
Packit |
78deda |
/* Instructions to OptParseOptions3 on how to parse our options.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
optStruct3 opt;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int option_def_index;
|
|
Packit |
78deda |
unsigned int replaceOpt, andOpt, orOpt, xorOpt;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(option_def, 100);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
option_def_index = 0; /* incremented by OPTENT3 */
|
|
Packit |
78deda |
OPTENT3(0, "replace", OPT_FLAG, NULL,
|
|
Packit |
78deda |
&replaceOpt, 0);
|
|
Packit |
78deda |
OPTENT3(0, "and", OPT_FLAG, NULL,
|
|
Packit |
78deda |
&andOpt, 0);
|
|
Packit |
78deda |
OPTENT3(0, "or", OPT_FLAG, NULL,
|
|
Packit |
78deda |
&orOpt, 0);
|
|
Packit |
78deda |
OPTENT3(0, "xor", OPT_FLAG, NULL,
|
|
Packit |
78deda |
&xorOpt, 0);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
opt.opt_table = option_def;
|
|
Packit |
78deda |
opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */
|
|
Packit |
78deda |
opt.allowNegNum = TRUE; /* We have parms that are negative numbers */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pm_optParseOptions3(&argc, (char **)argv, opt, sizeof opt, 0);
|
|
Packit |
78deda |
/* Uses and sets argc, argv, and some of *cmdlineP and others. */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (replaceOpt + andOpt + orOpt + xorOpt > 1)
|
|
Packit |
78deda |
pm_error("You may specify only one of -replace, -and, -or, and -xor");
|
|
Packit |
78deda |
|
|
Packit |
78deda |
cmdlineP->operation =
|
|
Packit |
78deda |
replaceOpt ? REPLACE :
|
|
Packit |
78deda |
andOpt ? AND :
|
|
Packit |
78deda |
orOpt ? OR :
|
|
Packit |
78deda |
xorOpt ? XOR :
|
|
Packit |
78deda |
replaceOpt;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (argc-1 >= 3) {
|
|
Packit |
78deda |
cmdlineP->insetFilename = argv[1];
|
|
Packit |
78deda |
cmdlineP->insertCol = atoi(argv[2]);
|
|
Packit |
78deda |
cmdlineP->insertRow = atoi(argv[3]);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (argc-1 >= 4) {
|
|
Packit |
78deda |
cmdlineP->baseFilename = argv[4];
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (argc-1 > 4)
|
|
Packit |
78deda |
pm_error("Too many arguments: %u. This program takes "
|
|
Packit |
78deda |
"at most 4", argc-1);
|
|
Packit |
78deda |
} else
|
|
Packit |
78deda |
cmdlineP->baseFilename = "-";
|
|
Packit |
78deda |
} else
|
|
Packit |
78deda |
pm_error("You must specify at least 3 arguments: \"from\" file "
|
|
Packit |
78deda |
"name, insert-at column, and insert-at row. "
|
|
Packit |
78deda |
"You specified %u", argc-1);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (streq(cmdlineP->baseFilename, "-") &&
|
|
Packit |
78deda |
streq(cmdlineP->insetFilename, "-"))
|
|
Packit |
78deda |
pm_error("You can't use Standard Input for both the input images");
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static unsigned char
|
|
Packit |
78deda |
leftBits(unsigned char const x,
|
|
Packit |
78deda |
unsigned int const n){
|
|
Packit |
78deda |
/*----------------------------------------------------------------------------
|
|
Packit |
78deda |
'x' with the leftmost (high) n bits retained and the rest cleared to zero.
|
|
Packit |
78deda |
-----------------------------------------------------------------------------*/
|
|
Packit |
78deda |
assert(n <= 8);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
return (x >> (8-n)) << (8-n);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static unsigned char
|
|
Packit |
78deda |
rightBits(unsigned char const x,
|
|
Packit |
78deda |
unsigned int const n){
|
|
Packit |
78deda |
/*----------------------------------------------------------------------------
|
|
Packit |
78deda |
The rightmost 'n' bits of 'x'.
|
|
Packit |
78deda |
-----------------------------------------------------------------------------*/
|
|
Packit |
78deda |
assert(n <= 8);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
return ((unsigned char)(x << (8-n))) >> (8-n);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
insertDirect(FILE * const ifP,
|
|
Packit |
78deda |
unsigned char * const destrow,
|
|
Packit |
78deda |
unsigned int const cols,
|
|
Packit |
78deda |
int const format,
|
|
Packit |
78deda |
enum boolOp const operation,
|
|
Packit |
78deda |
unsigned char * const buffer) {
|
|
Packit |
78deda |
/*----------------------------------------------------------------------------
|
|
Packit |
78deda |
Read the next row from PBM file 'ifP' and merge it according to
|
|
Packit |
78deda |
'operation' into 'destrow', flush left in packed PBM format.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
'cols' and 'format' describe the 'ifP' image.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
'buffer' is a scratch buffer for our use, at least wide enough to hold
|
|
Packit |
78deda |
a packed PBM row of 'ifP'.
|
|
Packit |
78deda |
-----------------------------------------------------------------------------*/
|
|
Packit |
78deda |
/* We use pbm_readpbmrow_packed() to read whole bytes rounded up and merge
|
|
Packit |
78deda |
those into 'destrow', which means we update more than we're supposed to
|
|
Packit |
78deda |
if the image is not a multiple of 8 columns. In that case, we then fix
|
|
Packit |
78deda |
up the last byte by replacing the bits from the original image that we
|
|
Packit |
78deda |
messed up.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
unsigned int const colBytes = pbm_packed_bytes(cols);
|
|
Packit |
78deda |
unsigned int const last = colBytes - 1;
|
|
Packit |
78deda |
unsigned char const origRight = destrow[last];
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (operation == REPLACE)
|
|
Packit |
78deda |
pbm_readpbmrow_packed(ifP, destrow, cols, format);
|
|
Packit |
78deda |
else {
|
|
Packit |
78deda |
unsigned int i;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pbm_readpbmrow_packed(ifP, buffer, cols, format);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (i = 0; i < colBytes; ++i) {
|
|
Packit |
78deda |
switch (operation) {
|
|
Packit |
78deda |
case AND: destrow[i] |= buffer[i]; break;
|
|
Packit |
78deda |
case OR : destrow[i] &= buffer[i]; break;
|
|
Packit |
78deda |
case XOR: destrow[i] = ~( destrow[i] ^ buffer[i] ) ; break;
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
case NAND: destrow[i] = ~( destrow[i] | buffer[i] ) ; break;
|
|
Packit |
78deda |
case NOR : destrow[i] = ~( destrow[i] & buffer[i] ) ; break;
|
|
Packit |
78deda |
case NXOR: destrow[i] ^= buffer[i] ; break;
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
case REPLACE: assert(false); break;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/* destrow[] now contains garbage in all but the cols % 8 leftmost bits of
|
|
Packit |
78deda |
the last byte we touched. Those are supposed to be unchanged from the
|
|
Packit |
78deda |
input, so we restore them now.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
if (cols % 8 > 0)
|
|
Packit |
78deda |
destrow[last] = leftBits(destrow[last], cols % 8)
|
|
Packit |
78deda |
| rightBits(origRight, 8 - cols % 8);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
insertShift(FILE * const ifP,
|
|
Packit |
78deda |
unsigned char * const destrow,
|
|
Packit |
78deda |
unsigned int const cols,
|
|
Packit |
78deda |
unsigned int const format,
|
|
Packit |
78deda |
unsigned int const offset,
|
|
Packit |
78deda |
enum boolOp const operation,
|
|
Packit |
78deda |
unsigned char * const buffer) {
|
|
Packit |
78deda |
/*----------------------------------------------------------------------------
|
|
Packit |
78deda |
Same as insertDirect(), but start merging 'offset' bits from the left
|
|
Packit |
78deda |
end of 'destrow'. 'offset' is less than 8.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
buffer[] is wide enough to hold a packed PBM row of *ifP plus two
|
|
Packit |
78deda |
bytes of margin.
|
|
Packit |
78deda |
-----------------------------------------------------------------------------*/
|
|
Packit |
78deda |
unsigned int const shiftByteCt = pbm_packed_bytes(cols + offset);
|
|
Packit |
78deda |
unsigned int const last = shiftByteCt - 1;
|
|
Packit |
78deda |
unsigned char const origLeft = destrow[0];
|
|
Packit |
78deda |
unsigned char const origRight = destrow[last];
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int const padOffset = (cols + offset) % 8;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int i;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
assert(offset < 8);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pbm_readpbmrow_packed(ifP, &buffer[1], cols, format);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/* Note that buffer[0] is undefined. */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (i = 0; i < shiftByteCt; ++i) {
|
|
Packit |
78deda |
unsigned int const rsh = offset;
|
|
Packit |
78deda |
unsigned int const lsh = 8-rsh;
|
|
Packit |
78deda |
unsigned char const t = buffer[i] << lsh | buffer[i+1] >> rsh;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
switch (operation) {
|
|
Packit |
78deda |
case REPLACE: destrow[i] = t; break;
|
|
Packit |
78deda |
case AND: destrow[i] |= t; break;
|
|
Packit |
78deda |
case OR : destrow[i] &= t; break;
|
|
Packit |
78deda |
case XOR: destrow[i] = ~ (destrow[i] ^ t); break;
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
case NAND: destrow[i] = ~ (destrow[i] | t); break;
|
|
Packit |
78deda |
case NOR : destrow[i] = ~ (destrow[i] & t); break;
|
|
Packit |
78deda |
case NXOR: destrow[i] ^= t; break;
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/* destrow[] now contains garbage in the 'offset' leftmost bits and
|
|
Packit |
78deda |
8-offset rightmost bits of the last byte we touched. Those are
|
|
Packit |
78deda |
supposed to be unchanged from the input, so we restore them now.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
destrow[0] = leftBits(origLeft, offset) |
|
|
Packit |
78deda |
rightBits(destrow[0], 8-offset);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (padOffset % 8 > 0)
|
|
Packit |
78deda |
destrow[last] = leftBits(destrow[last], padOffset) |
|
|
Packit |
78deda |
rightBits(origRight , 8-padOffset);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
pastePbm(FILE * const fpInset,
|
|
Packit |
78deda |
FILE * const fpBase,
|
|
Packit |
78deda |
int const insetFormat,
|
|
Packit |
78deda |
int const baseFormat,
|
|
Packit |
78deda |
unsigned int const insetRows,
|
|
Packit |
78deda |
unsigned int const baseRows,
|
|
Packit |
78deda |
unsigned int const insetCols,
|
|
Packit |
78deda |
unsigned int const baseCols,
|
|
Packit |
78deda |
unsigned int const insertCol,
|
|
Packit |
78deda |
unsigned int const insertRow,
|
|
Packit |
78deda |
enum boolOp const operation) {
|
|
Packit |
78deda |
/*----------------------------------------------------------------------------
|
|
Packit |
78deda |
Fast paste for PBM
|
|
Packit |
78deda |
-----------------------------------------------------------------------------*/
|
|
Packit |
78deda |
unsigned char * const baserow = pbm_allocrow_packed(baseCols);
|
|
Packit |
78deda |
unsigned char * const buffer = pbm_allocrow_packed(insetCols+16);
|
|
Packit |
78deda |
unsigned int const shiftByteCt = insertCol / 8;
|
|
Packit |
78deda |
unsigned int const shiftOffset = insertCol % 8;
|
|
Packit |
78deda |
unsigned int const baseColByteCt = pbm_packed_bytes(baseCols);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int row;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pbm_writepbminit(stdout, baseCols, baseRows, 0);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (row = 0; row < baseRows; ++row) {
|
|
Packit |
78deda |
pbm_readpbmrow_packed(fpBase, baserow, baseCols, baseFormat);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (row >= insertRow && row < insertRow + insetRows) {
|
|
Packit |
78deda |
if (shiftOffset == 0)
|
|
Packit |
78deda |
insertDirect(fpInset, &baserow[shiftByteCt], insetCols,
|
|
Packit |
78deda |
insetFormat, operation, buffer);
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
insertShift(fpInset, &baserow[shiftByteCt], insetCols,
|
|
Packit |
78deda |
insetFormat, shiftOffset, operation, buffer);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (baseCols % 8 > 0)
|
|
Packit |
78deda |
baserow[baseColByteCt-1]
|
|
Packit |
78deda |
= leftBits(baserow[baseColByteCt-1] , baseCols % 8);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pbm_writepbmrow_packed(stdout, baserow, baseCols, 0);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
pbm_freerow_packed(buffer);
|
|
Packit |
78deda |
pbm_freerow_packed(baserow);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
pasteNonPbm(FILE * const fpInset,
|
|
Packit |
78deda |
FILE * const fpBase,
|
|
Packit |
78deda |
int const formatInset,
|
|
Packit |
78deda |
int const formatBase,
|
|
Packit |
78deda |
int const newformat,
|
|
Packit |
78deda |
xelval const maxvalInset,
|
|
Packit |
78deda |
xelval const maxvalBase,
|
|
Packit |
78deda |
unsigned int const rowsInset,
|
|
Packit |
78deda |
unsigned int const rowsBase,
|
|
Packit |
78deda |
unsigned int const colsInset,
|
|
Packit |
78deda |
unsigned int const colsBase,
|
|
Packit |
78deda |
unsigned int const insertCol,
|
|
Packit |
78deda |
unsigned int const insertRow) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/* Logic works for PBM, but cannot do bitwise operations */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
xelval const newmaxval = MAX(maxvalInset, maxvalBase);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
xel * const xelrowInset = pnm_allocrow(colsInset);
|
|
Packit |
78deda |
xel * const xelrowBase = pnm_allocrow(colsBase);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int row;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnm_writepnminit(stdout, colsBase, rowsBase, newmaxval, newformat, 0);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (row = 0; row < rowsBase; ++row) {
|
|
Packit |
78deda |
pnm_readpnmrow(fpBase, xelrowBase, colsBase, maxvalBase, formatBase);
|
|
Packit |
78deda |
pnm_promoteformatrow(xelrowBase, colsBase, maxvalBase, formatBase,
|
|
Packit |
78deda |
newmaxval, newformat);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (row >= insertRow && row < insertRow + rowsInset) {
|
|
Packit |
78deda |
unsigned int colInset;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnm_readpnmrow(fpInset, xelrowInset, colsInset, maxvalInset,
|
|
Packit |
78deda |
formatInset);
|
|
Packit |
78deda |
pnm_promoteformatrow(xelrowInset, colsInset, maxvalInset,
|
|
Packit |
78deda |
formatInset, newmaxval, newformat );
|
|
Packit |
78deda |
for (colInset = 0; colInset < colsInset; ++colInset)
|
|
Packit |
78deda |
xelrowBase[insertCol + colInset] = xelrowInset[colInset];
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
pnm_writepnmrow(stdout, xelrowBase, colsBase, newmaxval, newformat, 0);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnm_freerow(xelrowBase);
|
|
Packit |
78deda |
pnm_freerow(xelrowInset);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
int
|
|
Packit |
78deda |
main(int argc, const char ** argv) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
struct CmdlineInfo cmdline;
|
|
Packit |
78deda |
FILE * fpInset;
|
|
Packit |
78deda |
FILE * fpBase;
|
|
Packit |
78deda |
xelval maxvalInset, maxvalBase;
|
|
Packit |
78deda |
int rowsInset, colsInset;
|
|
Packit |
78deda |
int formatInset;
|
|
Packit |
78deda |
int rowsBase, colsBase;
|
|
Packit |
78deda |
int formatBase;
|
|
Packit |
78deda |
int newformat;
|
|
Packit |
78deda |
unsigned int insertRow, insertCol;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pm_proginit(&argc, argv);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
parseCommandLine(argc, argv, &cmdline);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
fpInset = pm_openr(cmdline.insetFilename);
|
|
Packit |
78deda |
fpBase = pm_openr(cmdline.baseFilename);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnm_readpnminit(fpInset, &colsInset, &rowsInset,
|
|
Packit |
78deda |
&maxvalInset, &formatInset);
|
|
Packit |
78deda |
pnm_readpnminit(fpBase, &colsBase, &rowsBase, &maxvalBase, &formatBase);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (colsBase < colsInset)
|
|
Packit |
78deda |
pm_error(
|
|
Packit |
78deda |
"Image to paste is wider than base image by %u cols",
|
|
Packit |
78deda |
colsInset - colsBase);
|
|
Packit |
78deda |
else if (cmdline.insertCol <= -colsBase)
|
|
Packit |
78deda |
pm_error(
|
|
Packit |
78deda |
"x is too negative -- the second image has only %u cols",
|
|
Packit |
78deda |
colsBase);
|
|
Packit |
78deda |
else if (cmdline.insertCol >= colsBase)
|
|
Packit |
78deda |
pm_error(
|
|
Packit |
78deda |
"x is too large -- the second image has only %u cols",
|
|
Packit |
78deda |
colsBase);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (rowsBase < rowsInset)
|
|
Packit |
78deda |
pm_error(
|
|
Packit |
78deda |
"Image to paste is taller than base image by %u rows",
|
|
Packit |
78deda |
rowsInset - rowsBase);
|
|
Packit |
78deda |
else if (cmdline.insertRow <= -rowsBase)
|
|
Packit |
78deda |
pm_error(
|
|
Packit |
78deda |
"y is too negative -- the second image has only %u rows",
|
|
Packit |
78deda |
rowsBase);
|
|
Packit |
78deda |
else if (cmdline.insertRow >= rowsBase)
|
|
Packit |
78deda |
pm_error(
|
|
Packit |
78deda |
"y is too large -- the second image has only %d rows",
|
|
Packit |
78deda |
rowsBase);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
insertCol = cmdline.insertCol < 0 ?
|
|
Packit |
78deda |
colsBase + cmdline.insertCol : cmdline.insertCol;
|
|
Packit |
78deda |
insertRow = cmdline.insertRow < 0 ?
|
|
Packit |
78deda |
rowsBase + cmdline.insertRow : cmdline.insertRow;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (insertCol + colsInset > colsBase)
|
|
Packit |
78deda |
pm_error("Extends over right edge by %u pixels",
|
|
Packit |
78deda |
(insertCol + colsInset) - colsBase);
|
|
Packit |
78deda |
if (insertRow + rowsInset > rowsBase)
|
|
Packit |
78deda |
pm_error("Extends over bottom edge by %u pixels",
|
|
Packit |
78deda |
(insertRow + rowsInset) - rowsBase);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
newformat = MAX(PNM_FORMAT_TYPE(formatInset), PNM_FORMAT_TYPE(formatBase));
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (cmdline.operation != REPLACE && newformat != PBM_TYPE)
|
|
Packit |
78deda |
pm_error("no logical operations allowed for a non-PBM image");
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (newformat == PBM_TYPE)
|
|
Packit |
78deda |
pastePbm(fpInset, fpBase, formatInset, formatBase,
|
|
Packit |
78deda |
rowsInset, rowsBase, colsInset, colsBase,
|
|
Packit |
78deda |
insertCol, insertRow, cmdline.operation);
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
pasteNonPbm(fpInset, fpBase,
|
|
Packit |
78deda |
formatInset, formatBase, newformat,
|
|
Packit |
78deda |
maxvalInset, maxvalBase,
|
|
Packit |
78deda |
rowsInset, rowsBase, colsInset, colsBase,
|
|
Packit |
78deda |
insertCol, insertRow);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pm_close(fpInset);
|
|
Packit |
78deda |
pm_close(fpBase);
|
|
Packit |
78deda |
pm_close(stdout);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
return 0;
|
|
Packit |
78deda |
}
|