|
Packit |
78deda |
/*=============================================================================
|
|
Packit |
78deda |
pamenlarge
|
|
Packit |
78deda |
===============================================================================
|
|
Packit |
78deda |
By Bryan Henderson 2004.09.26. Contributed to the public domain by its
|
|
Packit |
78deda |
author.
|
|
Packit |
78deda |
=============================================================================*/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#include "netpbm/mallocvar.h"
|
|
Packit |
78deda |
#include "netpbm/pm_c_util.h"
|
|
Packit |
78deda |
#include "netpbm/pam.h"
|
|
Packit |
78deda |
#include "netpbm/pbm.h"
|
|
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 *inputFilespec;
|
|
Packit |
78deda |
unsigned int scaleFactor;
|
|
Packit |
78deda |
};
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
parseCommandLine(int const argc,
|
|
Packit |
78deda |
const char ** const 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 |
if (argc-1 < 1)
|
|
Packit |
78deda |
pm_error("You must specify at least one argument: The scale factor");
|
|
Packit |
78deda |
else {
|
|
Packit |
78deda |
cmdlineP->scaleFactor = atoi(argv[1]);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (cmdlineP->scaleFactor < 1)
|
|
Packit |
78deda |
pm_error("Scale factor must be an integer at least 1. "
|
|
Packit |
78deda |
"You specified '%s'", argv[1]);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (argc-1 >= 2)
|
|
Packit |
78deda |
cmdlineP->inputFilespec = argv[2];
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
cmdlineP->inputFilespec = "-";
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
makeOutputRowMap(tuple ** const outTupleRowP,
|
|
Packit |
78deda |
struct pam * const outpamP,
|
|
Packit |
78deda |
struct pam * const inpamP,
|
|
Packit |
78deda |
tuple * const inTuplerow) {
|
|
Packit |
78deda |
/*----------------------------------------------------------------------------
|
|
Packit |
78deda |
Create a tuple *outTupleRowP which is actually a row of pointers into
|
|
Packit |
78deda |
inTupleRow[], so as to map input pixels to output pixels by stretching.
|
|
Packit |
78deda |
-----------------------------------------------------------------------------*/
|
|
Packit |
78deda |
tuple * newtuplerow;
|
|
Packit |
78deda |
int col;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(newtuplerow, outpamP->width);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (col = 0 ; col < inpamP->width; ++col) {
|
|
Packit |
78deda |
unsigned int const scaleFactor = outpamP->width / inpamP->width;
|
|
Packit |
78deda |
unsigned int subcol;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (subcol = 0; subcol < scaleFactor; ++subcol)
|
|
Packit |
78deda |
newtuplerow[col * scaleFactor + subcol] = inTuplerow[col];
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
*outTupleRowP = newtuplerow;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
validateComputableDimensions(unsigned int const width,
|
|
Packit |
78deda |
unsigned int const height,
|
|
Packit |
78deda |
unsigned int const scaleFactor) {
|
|
Packit |
78deda |
/*----------------------------------------------------------------------------
|
|
Packit |
78deda |
Make sure that multiplication for output image width and height do not
|
|
Packit |
78deda |
overflow.
|
|
Packit |
78deda |
See validateComputetableSize() in libpam.c
|
|
Packit |
78deda |
and pbm_readpbminitrest() in libpbm2.c
|
|
Packit |
78deda |
-----------------------------------------------------------------------------*/
|
|
Packit |
78deda |
unsigned int const maxWidthHeight = INT_MAX - 2;
|
|
Packit |
78deda |
unsigned int const maxScaleFactor = maxWidthHeight / MAX(height, width);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (scaleFactor > maxScaleFactor)
|
|
Packit |
78deda |
pm_error("Scale factor '%u' too large. "
|
|
Packit |
78deda |
"The maximum for this %u x %u input image is %u.",
|
|
Packit |
78deda |
scaleFactor, width, height, maxScaleFactor);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
enlargePbmRowHorizontally(struct pam * const inpamP,
|
|
Packit |
78deda |
const unsigned char * const inrow,
|
|
Packit |
78deda |
unsigned int const inColChars,
|
|
Packit |
78deda |
unsigned int const outColChars,
|
|
Packit |
78deda |
unsigned int const scaleFactor,
|
|
Packit |
78deda |
unsigned char * const outrow) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static unsigned char const dbl[16] = {
|
|
Packit |
78deda |
0x00, 0x03, 0x0C, 0x0F, 0x30, 0x33, 0x3C, 0x3F,
|
|
Packit |
78deda |
0xC0, 0xC3, 0xCC, 0xCF, 0xF0, 0xF3, 0xFC, 0xFF };
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static unsigned char const trp1[8] = {
|
|
Packit |
78deda |
0x00, 0x03, 0x1C, 0x1F, 0xE0, 0xE3, 0xFC, 0xFF };
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static unsigned char const trp2[16] = {
|
|
Packit |
78deda |
0x00, 0x01, 0x0E, 0x0F, 0x70, 0x71, 0x7E, 0x7F,
|
|
Packit |
78deda |
0x80, 0x81, 0x8E, 0x8F, 0xF0, 0xF1, 0xFE, 0xFF };
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static unsigned char const trp3[8] = {
|
|
Packit |
78deda |
0x00, 0x07, 0x38, 0x3F, 0xC0, 0xC7, 0xF8, 0xFF };
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static unsigned char const quad[4] = { 0x00, 0x0F, 0xF0, 0xFF };
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static unsigned char const quin2[8] = {
|
|
Packit |
78deda |
0x00, 0x01, 0x3E, 0x3F, 0xC0, 0xC1, 0xFE, 0xFF };
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static unsigned char const quin4[8] = {
|
|
Packit |
78deda |
0x00, 0x03, 0x7C, 0x7F, 0x80, 0x83, 0xFC, 0xFF };
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static unsigned int const pair[4] = { 0x0000, 0x00FF, 0xFF00, 0xFFFF };
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int colChar;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
switch (scaleFactor) {
|
|
Packit |
78deda |
case 1: break; /* outrow set to inrow */
|
|
Packit |
78deda |
case 2: /* Make outrow using prefabricated parts (same for 3, 5). */
|
|
Packit |
78deda |
for (colChar = 0; colChar < inColChars; ++colChar) {
|
|
Packit |
78deda |
outrow[colChar*2] = dbl[(inrow[colChar] & 0xF0) >> 4];
|
|
Packit |
78deda |
outrow[colChar*2+1] = dbl[(inrow[colChar] & 0x0F) >> 0];
|
|
Packit |
78deda |
/* Possible outrow overrun by one byte. */
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
case 3:
|
|
Packit |
78deda |
for (colChar = 0; colChar < inColChars; ++colChar) {
|
|
Packit |
78deda |
outrow[colChar*3] = trp1[(inrow[colChar] & 0xF0) >> 5];
|
|
Packit |
78deda |
outrow[colChar*3+1] = trp2[(inrow[colChar] >> 2) & 0x0F];
|
|
Packit |
78deda |
outrow[colChar*3+2] = trp3[(inrow[colChar] >> 0) & 0x07];
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
case 4:
|
|
Packit |
78deda |
for (colChar = 0; colChar < inColChars; ++colChar) {
|
|
Packit |
78deda |
unsigned int i;
|
|
Packit |
78deda |
for (i = 0; i < 4; ++i)
|
|
Packit |
78deda |
outrow[colChar*4+i]=
|
|
Packit |
78deda |
quad[(inrow[colChar] >> (6 - 2 * i)) & 0x03];
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
case 5:
|
|
Packit |
78deda |
for (colChar = 0; colChar < inColChars; ++colChar) {
|
|
Packit |
78deda |
outrow[colChar*5] = pair [(inrow[colChar] >> 6) & 0x03] >> 5;
|
|
Packit |
78deda |
outrow[colChar*5+1] = quin2[(inrow[colChar] >> 4) & 0x07] >> 0;
|
|
Packit |
78deda |
outrow[colChar*5+2] = quad [(inrow[colChar] >> 3) & 0x03] >> 0;
|
|
Packit |
78deda |
outrow[colChar*5+3] = quin4[(inrow[colChar] >> 1) & 0x07] >> 0;
|
|
Packit |
78deda |
outrow[colChar*5+4] = pair [(inrow[colChar] >> 0) & 0x03] >> 3;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
case 6: /* Compound of 2 and 3 */
|
|
Packit |
78deda |
for (colChar = 0; colChar < inColChars; ++colChar) {
|
|
Packit |
78deda |
unsigned char const hi = dbl[(inrow[colChar] & 0xF0) >> 4];
|
|
Packit |
78deda |
unsigned char const lo = dbl[(inrow[colChar] & 0x0F) >> 0];
|
|
Packit |
78deda |
|
|
Packit |
78deda |
outrow[colChar*6] = trp1[(hi & 0xF0) >> 5];
|
|
Packit |
78deda |
outrow[colChar*6+1] = trp2[(hi >> 2) & 0x0F];
|
|
Packit |
78deda |
outrow[colChar*6+2] = trp3[hi & 0x07];
|
|
Packit |
78deda |
|
|
Packit |
78deda |
outrow[colChar*6+3] = trp1[(lo & 0xF0) >> 5];
|
|
Packit |
78deda |
outrow[colChar*6+4] = trp2[(lo >> 2) & 0x0F];
|
|
Packit |
78deda |
outrow[colChar*6+5] = trp3[lo & 0x07];
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
case 7:
|
|
Packit |
78deda |
for (colChar = 0; colChar < inColChars; ++colChar) {
|
|
Packit |
78deda |
uint32_t hi, lo;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
hi = inrow[colChar] >> 4;
|
|
Packit |
78deda |
hi = ((((hi>>1) * 0x00082080) | (0x01 & hi)) & 0x00204081 ) * 0x7F;
|
|
Packit |
78deda |
hi >>= 4;
|
|
Packit |
78deda |
outrow[colChar*7] = (unsigned char) ( hi >> 16);
|
|
Packit |
78deda |
outrow[colChar*7+1] = (unsigned char) ((hi >> 8) & 0xFF);
|
|
Packit |
78deda |
outrow[colChar*7+2] = (unsigned char) ((hi >> 0) & 0xFF);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
lo = inrow[colChar] & 0x001F;
|
|
Packit |
78deda |
lo = ((((lo>>1) * 0x02082080) | (0x01 & lo)) & 0x10204081 ) * 0x7F;
|
|
Packit |
78deda |
outrow[colChar*7+3] = (unsigned char) ((lo >> 24) & 0xFF);
|
|
Packit |
78deda |
outrow[colChar*7+4] = (unsigned char) ((lo >> 16) & 0xFF);
|
|
Packit |
78deda |
outrow[colChar*7+5] = (unsigned char) ((lo >> 8) & 0xFF);
|
|
Packit |
78deda |
outrow[colChar*7+6] = (unsigned char) ((lo >> 0) & 0xFF);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
case 8:
|
|
Packit |
78deda |
for (colChar = 0; colChar < inColChars; ++colChar) {
|
|
Packit |
78deda |
unsigned int i;
|
|
Packit |
78deda |
for (i = 0; i < 8; ++i) {
|
|
Packit |
78deda |
outrow[colChar*8+i] =
|
|
Packit |
78deda |
((inrow[colChar] >> (7-i)) & 0x01) *0xFF;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
case 9:
|
|
Packit |
78deda |
for (colChar = 0; colChar < inColChars; ++colChar) {
|
|
Packit |
78deda |
outrow[colChar*9] = ((inrow[colChar] >> 7) & 0x01) * 0xFF;
|
|
Packit |
78deda |
outrow[colChar*9+1] = pair[(inrow[colChar] >> 6) & 0x03] >> 1;
|
|
Packit |
78deda |
outrow[colChar*9+2] = pair[(inrow[colChar] >> 5) & 0x03] >> 2;
|
|
Packit |
78deda |
outrow[colChar*9+3] = pair[(inrow[colChar] >> 4) & 0x03] >> 3;
|
|
Packit |
78deda |
outrow[colChar*9+4] = pair[(inrow[colChar] >> 3) & 0x03] >> 4;
|
|
Packit |
78deda |
outrow[colChar*9+5] = pair[(inrow[colChar] >> 2) & 0x03] >> 5;
|
|
Packit |
78deda |
outrow[colChar*9+6] = pair[(inrow[colChar] >> 1) & 0x03] >> 6;
|
|
Packit |
78deda |
outrow[colChar*9+7] = pair[(inrow[colChar] >> 0) & 0x03] >> 7;
|
|
Packit |
78deda |
outrow[colChar*9+8] = (inrow[colChar] & 0x01) * 0xFF;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
case 10:
|
|
Packit |
78deda |
for (colChar = 0; colChar < inColChars; ++colChar) {
|
|
Packit |
78deda |
outrow[colChar*10] = ((inrow[colChar] >> 7) & 0x01 ) * 0xFF;
|
|
Packit |
78deda |
outrow[colChar*10+1] = pair[(inrow[colChar] >> 6) & 0x03] >> 2;
|
|
Packit |
78deda |
outrow[colChar*10+2] = pair[(inrow[colChar] >> 5) & 0x03] >> 4;
|
|
Packit |
78deda |
outrow[colChar*10+3] = pair[(inrow[colChar] >> 4) & 0x03] >> 6;
|
|
Packit |
78deda |
outrow[colChar*10+4] = ((inrow[colChar] >> 4) & 0x01) * 0xFF;
|
|
Packit |
78deda |
outrow[colChar*10+5] = ((inrow[colChar] >> 3) & 0x01) * 0xFF;
|
|
Packit |
78deda |
outrow[colChar*10+6] = pair[(inrow[colChar] >> 2) & 0x03] >> 2;
|
|
Packit |
78deda |
outrow[colChar*10+7] = pair[(inrow[colChar] >> 1) & 0x03] >> 4;
|
|
Packit |
78deda |
outrow[colChar*10+8] = pair[(inrow[colChar] >> 0) & 0x03] >> 6;
|
|
Packit |
78deda |
outrow[colChar*10+9] = ((inrow[colChar] >> 0) & 0x01) * 0xFF;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
default:
|
|
Packit |
78deda |
/* Unlike the above cases, we iterate through outrow. To compute the
|
|
Packit |
78deda |
color composition of each outrow byte, we consult a single bit or
|
|
Packit |
78deda |
two consecutive bits in inrow.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Color changes never happen twice in a single outrow byte.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
This is a generalization of above routines for scale factors
|
|
Packit |
78deda |
9 and 10.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Logic works for scale factors 4, 6, 7, 8, and above (but not 5).
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (colChar = 0; colChar < outColChars; ++colChar) {
|
|
Packit |
78deda |
unsigned int const mult = scaleFactor;
|
|
Packit |
78deda |
unsigned int const mod = colChar % mult;
|
|
Packit |
78deda |
unsigned int const bit = (mod*8)/mult;
|
|
Packit |
78deda |
/* source bit position, leftmost=0 */
|
|
Packit |
78deda |
unsigned int const offset = mult - (mod*8)%mult;
|
|
Packit |
78deda |
/* number of outrow bits derived from the same
|
|
Packit |
78deda |
"source" inrow bit, starting at and to the right
|
|
Packit |
78deda |
of leftmost bit of outrow byte, inclusive
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (offset >= 8) /* Bits in outrow byte are all 1 or 0 */
|
|
Packit |
78deda |
outrow[colChar] =
|
|
Packit |
78deda |
(inrow[colChar/mult] >> (7-bit) & 0x01) * 0xFF;
|
|
Packit |
78deda |
else /* Two inrow bits influence this outrow byte */
|
|
Packit |
78deda |
outrow[colChar] = (unsigned char)
|
|
Packit |
78deda |
(pair[inrow[colChar/mult] >> (6-bit) & 0x03] >> offset)
|
|
Packit |
78deda |
& 0xFF;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
enlargePbm(struct pam * const inpamP,
|
|
Packit |
78deda |
unsigned int const scaleFactor,
|
|
Packit |
78deda |
FILE * const ofP) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned char * inrow;
|
|
Packit |
78deda |
unsigned char * outrow;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int row;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int const outcols = inpamP->width * scaleFactor;
|
|
Packit |
78deda |
unsigned int const outrows = inpamP->height * scaleFactor;
|
|
Packit |
78deda |
unsigned int const inColChars = pbm_packed_bytes(inpamP->width);
|
|
Packit |
78deda |
unsigned int const outColChars = pbm_packed_bytes(outcols);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
inrow = pbm_allocrow_packed(inpamP->width);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (scaleFactor == 1)
|
|
Packit |
78deda |
outrow = inrow;
|
|
Packit |
78deda |
else {
|
|
Packit |
78deda |
/* Allow writes beyond outrow data end when scaleFactor is
|
|
Packit |
78deda |
one of the special fast cases: 2, 3, 4, 5, 6, 7, 8, 9, 10.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
unsigned int const rightPadding =
|
|
Packit |
78deda |
scaleFactor > 10 ? 0 : (scaleFactor - 1) * 8;
|
|
Packit |
78deda |
outrow = pbm_allocrow_packed(outcols + rightPadding);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pbm_writepbminit(ofP, outcols, outrows, 0);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (row = 0; row < inpamP->height; ++row) {
|
|
Packit |
78deda |
unsigned int i;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pbm_readpbmrow_packed(inpamP->file, inrow, inpamP->width,
|
|
Packit |
78deda |
inpamP->format);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (outcols % 8 > 0) /* clean final partial byte */
|
|
Packit |
78deda |
pbm_cleanrowend_packed(inrow, inpamP->width);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
enlargePbmRowHorizontally(inpamP, inrow, inColChars, outColChars,
|
|
Packit |
78deda |
scaleFactor, outrow);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (i = 0; i < scaleFactor; ++i)
|
|
Packit |
78deda |
pbm_writepbmrow_packed(ofP, outrow, outcols, 0);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (outrow != inrow)
|
|
Packit |
78deda |
pbm_freerow(outrow);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pbm_freerow(inrow);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
enlargeGeneral(struct pam * const inpamP,
|
|
Packit |
78deda |
unsigned int const scaleFactor,
|
|
Packit |
78deda |
FILE * const ofP) {
|
|
Packit |
78deda |
/*----------------------------------------------------------------------------
|
|
Packit |
78deda |
Enlarge the input image described by *pamP.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Assume the dimensions won't cause an arithmetic overflow.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
This works on all kinds of images, but is slower than enlargePbm on
|
|
Packit |
78deda |
PBM.
|
|
Packit |
78deda |
-----------------------------------------------------------------------------*/
|
|
Packit |
78deda |
struct pam outpam;
|
|
Packit |
78deda |
tuple * tuplerow;
|
|
Packit |
78deda |
tuple * newtuplerow;
|
|
Packit |
78deda |
unsigned int row;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
outpam = *inpamP;
|
|
Packit |
78deda |
outpam.file = ofP;
|
|
Packit |
78deda |
outpam.width = inpamP->width * scaleFactor;
|
|
Packit |
78deda |
outpam.height = inpamP->height * scaleFactor;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnm_writepaminit(&outpam);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
tuplerow = pnm_allocpamrow(inpamP);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
makeOutputRowMap(&newtuplerow, &outpam, inpamP, tuplerow);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (row = 0; row < inpamP->height; ++row) {
|
|
Packit |
78deda |
pnm_readpamrow(inpamP, tuplerow);
|
|
Packit |
78deda |
pnm_writepamrowmult(&outpam, newtuplerow, scaleFactor);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
free(newtuplerow);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnm_freepamrow(tuplerow);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
int
|
|
Packit |
78deda |
main(int argc,
|
|
Packit |
78deda |
const char ** argv) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
struct cmdlineInfo cmdline;
|
|
Packit |
78deda |
FILE * ifP;
|
|
Packit |
78deda |
struct pam inpam;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pm_proginit(&argc, argv);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
parseCommandLine(argc, argv, &cmdline);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
ifP = pm_openr(cmdline.inputFilespec);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type));
|
|
Packit |
78deda |
|
|
Packit |
78deda |
validateComputableDimensions(inpam.width, inpam.height,
|
|
Packit |
78deda |
cmdline.scaleFactor);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (PNM_FORMAT_TYPE(inpam.format) == PBM_TYPE)
|
|
Packit |
78deda |
enlargePbm(&inpam, cmdline.scaleFactor, stdout);
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
enlargeGeneral(&inpam, cmdline.scaleFactor, stdout);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pm_close(ifP);
|
|
Packit |
78deda |
pm_close(stdout);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
return 0;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|