diff --git a/netpbm-pnmmontagefix.patch b/netpbm-pnmmontagefix.patch new file mode 100644 index 0000000..fb715b8 --- /dev/null +++ b/netpbm-pnmmontagefix.patch @@ -0,0 +1,832 @@ +diff -up netpbm-10.47.05/editor/pnmmontage.c.pnmmontagefix netpbm-10.47.05/editor/pnmmontage.c +--- netpbm-10.47.05/editor/pnmmontage.c.pnmmontagefix 2009-12-10 08:34:32.000000000 +0100 ++++ netpbm-10.47.05/editor/pnmmontage.c 2010-03-16 20:47:38.000000000 +0100 +@@ -10,136 +10,19 @@ + * implied warranty. + */ + +-#define _BSD_SOURCE /* Make sure strdup() is in */ +-#include + #include + #include + +-#include "pm_c_util.h" +-#include "mallocvar.h" +-#include "nstring.h" +-#include "shhopt.h" + #include "pam.h" ++#include "shhopt.h" ++#include "nstring.h" ++#include "mallocvar.h" + ++typedef struct { int f[sizeof(int) * 8 + 1]; } factorset; ++typedef struct { int x; int y; } coord; + +- +-struct cmdlineInfo { +- const char * header; +- const char * data; +- const char * prefix; +- unsigned int quality; +- unsigned int quality2; +- unsigned int nFiles; +- const char ** inFileName; +-}; +- +- +- +-static void +-parseCommandLine(int argc, const char ** argv, +- struct cmdlineInfo * const cmdlineP) { +-/*---------------------------------------------------------------------------- +- parse program command line described in Unix standard form by argc +- and argv. Return the information in the options as *cmdlineP. +- +- If command line is internally inconsistent (invalid options, etc.), +- issue error message to stderr and abort program. +- +- Note that the strings we return are stored in the storage that +- was passed to us as the argv array. We also trash *argv. +------------------------------------------------------------------------------*/ +- optEntry * option_def; +- /* Instructions to OptParseOptions3 on how to parse our options. */ +- optStruct3 opt; +- unsigned int dataSpec, headerSpec, prefixSpec, qualitySpec; +- unsigned int option_def_index; +- unsigned int i; +- unsigned int q[10]; +- +- MALLOCARRAY_NOFAIL(option_def, 100); +- +- option_def_index = 0; /* incremented by OPTENTRY */ +- OPTENT3( 0, "data", OPT_STRING, &cmdlineP->data, &dataSpec, 0); +- OPTENT3( 0, "header", OPT_STRING, &cmdlineP->header, &headerSpec, 0); +- OPTENT3('q', "quality", OPT_UINT, &cmdlineP->quality, &qualitySpec, 0); +- OPTENT3('p', "prefix", OPT_STRING, &cmdlineP->prefix, &prefixSpec, 0); +- OPTENT3('0', "0", OPT_FLAG, NULL, &q[0], 0); +- OPTENT3('1', "1", OPT_FLAG, NULL, &q[1], 0); +- OPTENT3('2', "2", OPT_FLAG, NULL, &q[2], 0); +- OPTENT3('3', "3", OPT_FLAG, NULL, &q[3], 0); +- OPTENT3('4', "4", OPT_FLAG, NULL, &q[4], 0); +- OPTENT3('5', "5", OPT_FLAG, NULL, &q[5], 0); +- OPTENT3('6', "6", OPT_FLAG, NULL, &q[6], 0); +- OPTENT3('7', "7", OPT_FLAG, NULL, &q[7], 0); +- OPTENT3('8', "8", OPT_FLAG, NULL, &q[8], 0); +- OPTENT3('9', "9", OPT_FLAG, NULL, &q[9], 0); +- +- opt.opt_table = option_def; +- opt.short_allowed = FALSE; +- opt.allowNegNum = FALSE; +- +- optParseOptions3(&argc, (char**)argv, opt, sizeof(opt), 0); +- +- if (!dataSpec) +- cmdlineP->data = NULL; +- if (!headerSpec) +- cmdlineP->header = NULL; +- if (!prefixSpec) +- cmdlineP->prefix = ""; +- if (!qualitySpec) +- cmdlineP->quality = 200; +- +- +- /* cmdlineP->quality2 is the greatest number from the --1, --2, etc. +- options, or 5 if none of those are specified. +- */ +- cmdlineP->quality2 = 5; /* initial value */ +- for (i = 0; i < 10; ++i) { +- if (q[i]) +- cmdlineP->quality2 = i; +- } +- +- cmdlineP->nFiles = argc-1; +- +- MALLOCARRAY_NOFAIL(cmdlineP->inFileName, argc-1); +- +- for (i = 0; i < argc-1; ++i) { +- if (cmdlineP->data && strchr(argv[i+1], ':')) +- pm_error("Filename '%s' contains a \":\", which is forbidden " +- "with -data", argv[i+1]); +- else +- cmdlineP->inFileName[i] = strdup(argv[1+1]); +- } +-} +- +- +- +-typedef struct { +- int f[sizeof(int) * 8 + 1]; +-} factorset; +- +-typedef struct { +- int x; int y; +-} coord; +- +-typedef struct { +- coord ul; +- coord size; +-} rectangle; +- +-static coord +-lr(rectangle const r) { +-/*---------------------------------------------------------------------------- +- Return the coordinates of the lower right corner of 'r' +- (i.e. the pixel just beyond the lowest rightmost one). +------------------------------------------------------------------------------*/ +- coord retval; +- +- retval.x = r.ul.x + r.size.x; +- retval.y = r.ul.y + r.size.y; +- +- return retval; +-} ++static int qfactor = 200; ++static int quality = 5; + + static factorset + factor(int n) +@@ -180,151 +63,109 @@ gcd(int n, int m) + return (g); + } + ++static __inline__ int imax(int n, int m) { return (n > m ? n : m); } + +- +-static bool +-overlaps(rectangle const a, +- rectangle const b) { +- +- return +- (a.ul.x < lr(b).x && a.ul.y < lr(b).y) && +- (lr(a).x > b.ul.x && lr(a).y > b.ul.y); +-} +- +- +- +-static bool +-collides(rectangle const test, +- const rectangle * const fieldList, +- unsigned int const n) { +-/*---------------------------------------------------------------------------- +- Return true iff the rectangle 'test' overlaps any of the 'n' rectangles +- fieldList[]. +------------------------------------------------------------------------------*/ +- unsigned int i; +- +- for (i = 0; i < n; ++i) +- if (overlaps(fieldList[i], test)) +- return true; +- +- return false; ++static int ++checkcollision(coord *locs, coord *szs, coord *cloc, coord *csz, int n) ++{ ++ int i; ++ for (i = 0; i < n; ++i) ++ { ++ if ((locs[i].x < cloc->x + csz->x) && ++ (locs[i].y < cloc->y + csz->y) && ++ (locs[i].x + szs[i].x > cloc->x) && ++ (locs[i].y + szs[i].y > cloc->y)) ++ return (1); ++ } ++ return (0); + } + +- +- + static void +-recursefindpack(rectangle * const current, +- coord const currentsz, +- coord * const best, +- unsigned int const minarea, +- unsigned int * const maxareaP, +- unsigned int const depth, +- unsigned int const n, +- unsigned int const xinc, +- unsigned int const yinc, +- unsigned int const quality, +- unsigned int const qfactor) { +- +- if (depth == n) { +- if (currentsz.x * currentsz.y < *maxareaP) { +- unsigned int i; +- for (i = 0; i < n; ++i) +- best[i] = current[i].ul; +- *maxareaP = currentsz.x * currentsz.y; +- } +- } else { +- unsigned int i; +- +- rectangle * const newP = ¤t[depth]; ++recursefindpack(coord *current, coord currentsz, coord *set, ++ coord *best, int minarea, int *maxarea, ++ int depth, int n, int xinc, int yinc) ++{ ++ coord c; ++ if (depth == n) ++ { ++ if (currentsz.x * currentsz.y < *maxarea) ++ { ++ memcpy(best, current, sizeof(coord) * n); ++ *maxarea = currentsz.x * currentsz.y; ++ } ++ return; ++ } + +- for (i = 0; ; ++i) { +- for (newP->ul.x = 0, newP->ul.y = i * yinc; +- newP->ul.y <= i * yinc;) { +- +- coord c; +- +- c.x = MAX(lr(*newP).x, currentsz.x); +- c.y = MAX(lr(*newP).y, currentsz.y); +- pm_message("current = (%u.%u, %u.%u) new = (%u.%u, %u.%u)", +- current[0].ul.x, current[0].size.x, +- current[0].ul.y, current[0].size.y, +- newP->ul.x, newP->size.x, +- newP->ul.y, newP->size.y); +- if (!collides(*newP, current, depth)) { +- pm_message("Depth %u: Doesn't collide at i=%u", depth,i); +- recursefindpack(current, c, best, minarea, maxareaP, +- depth + 1, n, xinc, yinc, +- quality, qfactor); +- if (*maxareaP <= minarea) +- return; +- } +- if (newP->ul.x == (i - 1) * xinc) +- newP->ul.y = 0; +- if (newP->ul.x < i * xinc) +- newP->ul.x += xinc; +- else +- newP->ul.y += yinc; +- } +- } ++ for (current[depth].x = 0; ++ imax(current[depth].x + set[depth].x, currentsz.x) * ++ imax(currentsz.y, set[depth].y) < *maxarea; ++ current[depth].x += xinc) ++ { ++ for (current[depth].y = 0; ++ imax(current[depth].x + set[depth].x, currentsz.x) * ++ imax(currentsz.y, current[depth].y + set[depth].y) < *maxarea; ++ current[depth].y += yinc) ++ { ++ c.x = imax(current[depth].x + set[depth].x, currentsz.x); ++ c.y = imax(current[depth].y + set[depth].y, currentsz.y); ++ if (!checkcollision(current, set, ¤t[depth], &set[depth], depth)) ++ { ++ recursefindpack(current, c, set, best, minarea, maxarea, ++ depth + 1, n, xinc, yinc); ++ if (*maxarea <= minarea) ++ return; ++ } + } ++ } + } + +- +- + static void +-findpack(struct pam * const imgs, +- unsigned int const n, +- coord * const coords, +- unsigned int const quality, +- unsigned int const qfactor) { ++findpack(struct pam *imgs, int n, coord *coords) ++{ ++ int minarea; ++ int i; ++ int rdiv; ++ int cdiv; ++ int minx = -1; ++ int miny = -1; ++ coord *current; ++ coord *set; ++ int z = INT_MAX; ++ coord c = { 0, 0 }; + +- int minarea; +- int i; +- int rdiv; +- int cdiv; +- int minx; +- int miny; +- rectangle * current; +- unsigned int z; +- coord c; +- +- minx = -1; miny = -1; /* initial value */ +- z = UINT_MAX; /* initial value */ +- c.x = 0; c.y = 0; /* initial value */ +- +- if (quality > 1) { +- unsigned int realMinarea; +- for (realMinarea = i = 0; i < n; ++i) +- realMinarea += imgs[i].height * imgs[i].width, +- minx = MAX(minx, imgs[i].width), +- miny = MAX(miny, imgs[i].height); +- +- minarea = realMinarea * qfactor / 100; +- } else { +- minarea = INT_MAX - 1; +- } ++ if (quality > 1) ++ { ++ for (minarea = i = 0; i < n; ++i) ++ minarea += imgs[i].height * imgs[i].width, ++ minx = imax(minx, imgs[i].width), ++ miny = imax(miny, imgs[i].height); + +- /* It's relatively easy to show that, if all the images +- * are multiples of a particular size, then a best +- * packing will always align the images on a grid of +- * that size. +- * +- * This speeds computation immensely. +- */ +- for (rdiv = imgs[0].height, i = 1; i < n; ++i) +- rdiv = gcd(imgs[i].height, rdiv); +- +- for (cdiv = imgs[0].width, i = 1; i < n; ++i) +- cdiv = gcd(imgs[i].width, cdiv); +- +- MALLOCARRAY(current, n); +- +- for (i = 0; i < n; ++i) { +- current[i].size.x = imgs[i].width; +- current[i].size.y = imgs[i].height; +- } +- recursefindpack(current, c, coords, minarea, &z, 0, n, cdiv, rdiv, +- quality, qfactor); ++ minarea = minarea * qfactor / 100; ++ } ++ else ++ { ++ minarea = INT_MAX - 1; ++ } ++ ++ /* It's relatively easy to show that, if all the images ++ * are multiples of a particular size, then a best ++ * packing will always align the images on a grid of ++ * that size. ++ * ++ * This speeds computation immensely. ++ */ ++ for (rdiv = imgs[0].height, i = 1; i < n; ++i) ++ rdiv = gcd(imgs[i].height, rdiv); ++ ++ for (cdiv = imgs[0].width, i = 1; i < n; ++i) ++ cdiv = gcd(imgs[i].width, cdiv); ++ ++ MALLOCARRAY(current, n); ++ MALLOCARRAY(set, n); ++ for (i = 0; i < n; ++i) ++ set[i].x = imgs[i].width, ++ set[i].y = imgs[i].height; ++ recursefindpack(current, c, set, coords, minarea, &z, 0, n, cdiv, rdiv); + } + + +@@ -396,264 +237,204 @@ writePam(struct pam * const outpam + + + +-static void +-writeData(FILE * const dataFileP, +- unsigned int const width, +- unsigned int const height, +- unsigned int const nfiles, +- const char ** const names, +- const coord * const coords, +- const struct pam * const imgs) { +- +- unsigned int i; +- +- fprintf(dataFileP, ":0:0:%u:%u\n", width, height); +- +- for (i = 0; i < nfiles; ++i) { +- fprintf(dataFileP, "%s:%u:%u:%u:%u\n", names[i], coords[i].x, +- coords[i].y, imgs[i].width, imgs[i].height); +- } +-} +- +- +- +-static void +-writeHeader(FILE * const headerFileP, +- const char * const prefix, +- unsigned int const width, +- unsigned int const height, +- unsigned int const nfiles, +- const char ** const names, +- const coord * const coords, +- const struct pam * imgs) { +- +- unsigned int i; +- +- fprintf(headerFileP, "#define %sOVERALLX %u\n", prefix, width); +- +- fprintf(headerFileP, "#define %sOVERALLY %u\n", prefix, height); +- +- fprintf(headerFileP, "\n"); +- +- for (i = 0; i < nfiles; ++i) { +- char * const buffer = strdup(names[i]); +- coord const coord = coords[i]; +- struct pam const img = imgs[i]; +- +- unsigned int j; +- +- *strchr(buffer, '.') = 0; +- for (j = 0; buffer[j]; ++j) { +- if (ISLOWER(buffer[j])) +- buffer[j] = TOUPPER(buffer[j]); +- } +- fprintf(headerFileP, "#define %s%sX %u\n", +- prefix, buffer, coord.x); +- +- fprintf(headerFileP, "#define %s%sY %u\n", +- prefix, buffer, coord.y); +- +- fprintf(headerFileP, "#define %s%sSZX %u\n", +- prefix, buffer, img.width); +- +- fprintf(headerFileP, "#define %s%sSZY %u\n", +- prefix, buffer, img.height); +- +- fprintf(headerFileP, "\n"); +- } +-} ++int ++main(int argc, char **argv) ++{ ++ struct pam *imgs; ++ struct pam outimg; ++ struct pam p; ++ int nfiles; ++ int i, j; ++ unsigned int q[10]; ++ coord *coords; ++ const char *headfname = NULL; ++ const char *datafname = NULL; ++ const char *prefix = ""; ++ FILE *header; ++ FILE *data; ++ char **names; ++ char *c; ++ ++ optEntry *option_def = malloc(100*sizeof(optEntry)); ++ /* Instructions to OptParseOptions3 on how to parse our options. ++ */ ++ optStruct3 opt; ++ ++ unsigned int option_def_index; ++ ++ option_def_index = 0; /* incremented by OPTENTRY */ ++ OPTENT3( 0, "data", OPT_STRING, &datafname, NULL, 0); ++ OPTENT3( 0, "header", OPT_STRING, &headfname, NULL, 0); ++ OPTENT3('q', "quality", OPT_UINT, &qfactor, NULL, 0); ++ OPTENT3('p', "prefix", OPT_STRING, &prefix, NULL, 0); ++ OPTENT3('0', "0", OPT_FLAG, NULL, &q[0], 0); ++ OPTENT3('1', "1", OPT_FLAG, NULL, &q[1], 0); ++ OPTENT3('2', "2", OPT_FLAG, NULL, &q[2], 0); ++ OPTENT3('3', "3", OPT_FLAG, NULL, &q[3], 0); ++ OPTENT3('4', "4", OPT_FLAG, NULL, &q[4], 0); ++ OPTENT3('5', "5", OPT_FLAG, NULL, &q[5], 0); ++ OPTENT3('6', "6", OPT_FLAG, NULL, &q[6], 0); ++ OPTENT3('7', "7", OPT_FLAG, NULL, &q[7], 0); ++ OPTENT3('8', "8", OPT_FLAG, NULL, &q[8], 0); ++ OPTENT3('9', "9", OPT_FLAG, NULL, &q[9], 0); ++ ++ opt.opt_table = option_def; ++ opt.short_allowed = FALSE; ++ opt.allowNegNum = FALSE; ++ ++ pnm_init(&argc, argv); ++ ++ /* Check for flags. */ ++ optParseOptions3(&argc, argv, opt, sizeof(opt), 0); + ++ if (headfname) ++ header = pm_openw(headfname); + ++ if (datafname) ++ data = pm_openw(datafname); + +-static void +-sortImagesByArea(unsigned int const nfiles, +- struct pam * const imgs, +- const char ** const names) { +-/*---------------------------------------------------------------------------- +- Sort the images described by 'imgs' and 'names' in place, from largest +- area to smallest. +------------------------------------------------------------------------------*/ +- /* Bubble sort */ +- +- unsigned int i; +- +- for (i = 0; i < nfiles - 1; ++i) { +- unsigned int j; +- for (j = i + 1; j < nfiles; ++j) { +- if (imgs[j].width * imgs[j].height > +- imgs[i].width * imgs[i].height) { +- +- struct pam p; +- const char * c; +- +- p = imgs[i]; imgs[i] = imgs[j]; imgs[j] = p; +- c = names[i]; names[i] = names[j]; names[j] = c; +- } +- } ++ for (i = 0; i < 10; ++i) ++ { ++ if (q[i]) ++ { ++ quality = i; ++ switch (quality) ++ { ++ case 0: case 1: break; ++ case 2: case 3: case 4: case 5: case 6: ++ qfactor = 100 * (8 - quality); ++ break; ++ case 7: qfactor = 150; break; ++ case 8: qfactor = 125; break; ++ case 9: qfactor = 100; break; ++ } + } +-} +- ++ } + ++ if (1 < argc) ++ nfiles = argc - 1; ++ else ++ nfiles = 1; ++ ++ MALLOCARRAY(imgs, nfiles); ++ MALLOCARRAY(coords, nfiles); ++ MALLOCARRAY(names, nfiles); ++ ++ if (!imgs || !coords || !names) ++ pm_error("out of memory"); + +-static void +-computeOutputType(sample * const maxvalP, +- int * const formatP, +- char * const tupleTypeP, +- unsigned int * const depthP, +- unsigned int const nfiles, +- const struct pam * const imgs) { +- +- unsigned int i; +- +- sample maxval; +- int format; +- const char * tupleType; +- unsigned int depth; +- +- assert(nfiles > 0); +- +- /* initial guesses */ +- maxval = imgs[0].maxval; +- format = imgs[0].format; +- depth = imgs[0].depth; +- tupleType = imgs[0].tuple_type; +- +- for (i = 1; i < nfiles; ++i) { +- if (PAM_FORMAT_TYPE(imgs[i].format) > PAM_FORMAT_TYPE(format)) { +- format = imgs[i].format; +- tupleType = imgs[i].tuple_type; +- } +- maxval = MAX(maxval, imgs[i].maxval); +- depth = MAX(depth, imgs[i].depth); ++ if (1 < argc) ++ { ++ for (i = 0; i < nfiles; ++i) ++ { ++ if (strchr(argv[i+1], ':')) ++ { ++ imgs[i].file = pm_openr(strchr(argv[i+1], ':') + 1); ++ *strchr(argv[i+1], ':') = 0; ++ names[i] = argv[i+1]; ++ } ++ else ++ { ++ imgs[i].file = pm_openr(argv[i+1]); ++ names[i] = argv[i+1]; ++ } + } ++ } ++ else ++ { ++ imgs[0].file = stdin; ++ } + +- *maxvalP = maxval; +- *formatP = format; +- *depthP = depth; +- memcpy(tupleTypeP, tupleType, sizeof(imgs[0].tuple_type)); +-} ++ pnm_readpaminit(imgs[0].file, &imgs[0], PAM_STRUCT_SIZE(tuple_type)); ++ memset(&outimg, 0, sizeof(outimg)); ++ outimg.maxval = imgs[0].maxval; ++ outimg.format = imgs[0].format; ++ memcpy(outimg.tuple_type, imgs[0].tuple_type, sizeof(imgs[0].tuple_type)); ++ outimg.depth = imgs[0].depth; + ++ for (i = 1; i < nfiles; ++i) ++ { ++ pnm_readpaminit(imgs[i].file, &imgs[i], PAM_STRUCT_SIZE(tuple_type)); ++ if (PAM_FORMAT_TYPE(imgs[i].format) > PAM_FORMAT_TYPE(outimg.format)) ++ outimg.format = imgs[i].format, ++ memcpy(outimg.tuple_type, imgs[i].tuple_type, ++ sizeof(imgs[i].tuple_type)); ++ outimg.maxval = imax(imgs[i].maxval, outimg.maxval); ++ outimg.depth = imax(imgs[i].depth, outimg.depth); ++ } + ++ for (i = 0; i < nfiles - 1; ++i) ++ for (j = i + 1; j < nfiles; ++j) ++ if (imgs[j].width * imgs[j].height > imgs[i].width * imgs[i].height) ++ p = imgs[i], imgs[i] = imgs[j], imgs[j] = p, ++ c = names[i], names[i] = names[j], names[j] = c; + +-static void +-computeOutputDimensions(int * const widthP, +- int * const heightP, +- unsigned int const nfiles, +- const struct pam * const imgs, +- const coord * const coords) { +- +- unsigned int widthGuess, heightGuess; +- unsigned int i; +- +- widthGuess = 0; /* initial value */ +- heightGuess = 0; /* initial value */ +- +- for (i = 0; i < nfiles; ++i) { +- widthGuess = MAX(widthGuess, imgs[i].width + coords[i].x); +- heightGuess = MAX(heightGuess, imgs[i].height + coords[i].y); +- } ++ findpack(imgs, nfiles, coords); + +- *widthP = widthGuess; +- *heightP = heightGuess; +-} ++ outimg.height = outimg.width = 0; ++ for (i = 0; i < nfiles; ++i) ++ { ++ outimg.width = imax(outimg.width, imgs[i].width + coords[i].x); ++ outimg.height = imax(outimg.height, imgs[i].height + coords[i].y); ++ } + ++ outimg.size = sizeof(outimg); ++ outimg.len = sizeof(outimg); ++ outimg.file = stdout; ++ outimg.bytes_per_sample = 0; ++ for (i = outimg.maxval; i; i >>= 8) ++ ++outimg.bytes_per_sample; + ++ writePam(&outimg, nfiles, coords, imgs); + +-int +-main(int argc, const char **argv) { ++ if (datafname) ++ { ++ fprintf(data, ":0:0:%u:%u\n", outimg.width, outimg.height); + +- struct cmdlineInfo cmdline; +- struct pam * imgs; +- struct pam outimg; +- unsigned int nfiles; +- coord * coords; +- FILE * header; +- FILE * data; +- const char ** names; +- unsigned int i; +- unsigned int qfactor; /* In per cent */ +- +- pm_proginit(&argc, argv); +- +- parseCommandLine(argc, argv, &cmdline); +- +- header = cmdline.header ? pm_openw(cmdline.header) : NULL; +- data = cmdline.data ? pm_openw(cmdline.data) : NULL; +- +- switch (cmdline.quality2) { +- case 0: case 1: +- qfactor = cmdline.quality; +- break; +- case 2: case 3: case 4: case 5: case 6: +- qfactor = 100 * (8 - cmdline.quality2); +- break; +- case 7: qfactor = 150; break; +- case 8: qfactor = 125; break; +- case 9: qfactor = 100; break; +- default: pm_error("Internal error - impossible value of 'quality2': %u", +- cmdline.quality2); ++ for (i = 0; i < nfiles; ++i) ++ { ++ fprintf(data, "%s:%u:%u:%u:%u\n", names[i], coords[i].x, ++ coords[i].y, imgs[i].width, imgs[i].height); + } ++ } + +- nfiles = cmdline.nFiles > 0 ? cmdline.nFiles : 1; +- +- MALLOCARRAY(imgs, nfiles); +- MALLOCARRAY(coords, nfiles); +- MALLOCARRAY(names, nfiles); +- +- if (!imgs || !coords || !names) +- pm_error("out of memory"); +- +- if (cmdline.nFiles > 0) { +- unsigned int i; +- +- for (i = 0; i < cmdline.nFiles; ++i) { +- imgs[i].file = pm_openr(cmdline.inFileName[i]); +- names[i] = strdup(cmdline.inFileName[i]); +- } +- } else { +- imgs[0].file = stdin; +- names[0] = strdup("stdin"); +- } ++ if (headfname) ++ { ++ fprintf(header, "#define %sOVERALLX %u\n" ++ "#define %sOVERALLY %u\n" ++ "\n", ++ prefix, outimg.width, ++ prefix, outimg.height); + + for (i = 0; i < nfiles; ++i) +- pnm_readpaminit(imgs[i].file, &imgs[i], PAM_STRUCT_SIZE(tuple_type)); +- +- sortImagesByArea(nfiles, imgs, names); +- +- findpack(imgs, nfiles, coords, cmdline.quality2, qfactor); +- +- computeOutputType(&outimg.maxval, &outimg.format, outimg.tuple_type, +- &outimg.depth, nfiles, imgs); +- +- computeOutputDimensions(&outimg.width, &outimg.height, nfiles, +- imgs, coords); +- +- pnm_setminallocationdepth(&outimg, outimg.depth); +- +- outimg.size = sizeof(outimg); +- outimg.len = sizeof(outimg); +- outimg.file = stdout; +- outimg.bytes_per_sample = 0; +- for (i = outimg.maxval; i; i >>= 8) +- ++outimg.bytes_per_sample; +- +- writePam(&outimg, nfiles, coords, imgs); ++ { ++ *strchr(names[i], '.') = 0; ++ for (j = 0; names[i][j]; ++j) ++ { ++ if (ISLOWER(names[i][j])) ++ names[i][j] = TOUPPER(names[i][j]); ++ } ++ fprintf(header, "#define %s%sX %u\n" ++ "#define %s%sY %u\n" ++ "#define %s%sSZX %u\n" ++ "#define %s%sSZY %u\n" ++ "\n", ++ prefix, names[i], coords[i].x, ++ prefix, names[i], coords[i].y, ++ prefix, names[i], imgs[i].width, ++ prefix, names[i], imgs[i].height); ++ } ++ } + +- if (data) +- writeData(data, outimg.width, outimg.height, +- nfiles, names, coords, imgs); ++ for (i = 0; i < nfiles; ++i) ++ pm_close(imgs[i].file); ++ pm_close(stdout); + +- if (header) +- writeHeader(header, cmdline.prefix, outimg.width, outimg.height, +- nfiles, names, coords, imgs); ++ if (headfname) ++ pm_close(header); + +- for (i = 0; i < nfiles; ++i) +- pm_close(imgs[i].file); +- pm_close(stdout); +- if (header) +- pm_close(header); +- if (data) +- pm_close(data); ++ if (datafname) ++ pm_close(data); + +- return 0; ++ return 0; + } diff --git a/netpbm-security-scripts.patch b/netpbm-security-scripts.patch index 63005d1..557914b 100644 --- a/netpbm-security-scripts.patch +++ b/netpbm-security-scripts.patch @@ -1,6 +1,6 @@ -diff -up netpbm-10.47.06/converter/other/anytopnm.security-scripts netpbm-10.47.06/converter/other/anytopnm ---- netpbm-10.47.06/converter/other/anytopnm.security-scripts 2009-12-13 20:27:05.000000000 +0100 -+++ netpbm-10.47.06/converter/other/anytopnm 2009-12-16 18:59:17.000000000 +0100 +diff -up netpbm-10.47.05/converter/other/anytopnm.security-scripts netpbm-10.47.05/converter/other/anytopnm +--- netpbm-10.47.05/converter/other/anytopnm.security-scripts 2009-12-10 08:34:36.000000000 +0100 ++++ netpbm-10.47.05/converter/other/anytopnm 2010-03-16 21:28:09.000000000 +0100 @@ -510,10 +510,7 @@ else inputFile="-" fi @@ -31,10 +31,10 @@ diff -up netpbm-10.47.06/converter/other/anytopnm.security-scripts netpbm-10.47. +fi + exit 0 -diff -up netpbm-10.47.06/editor/pamstretch-gen.security-scripts netpbm-10.47.06/editor/pamstretch-gen ---- netpbm-10.47.06/editor/pamstretch-gen.security-scripts 2009-12-13 20:26:58.000000000 +0100 -+++ netpbm-10.47.06/editor/pamstretch-gen 2009-12-16 18:59:17.000000000 +0100 -@@ -31,9 +31,7 @@ if [ "$1" = "" ]; then +diff -up netpbm-10.47.05/editor/pamstretch-gen.security-scripts netpbm-10.47.05/editor/pamstretch-gen +--- netpbm-10.47.05/editor/pamstretch-gen.security-scripts 2009-12-10 08:34:32.000000000 +0100 ++++ netpbm-10.47.05/editor/pamstretch-gen 2010-03-16 21:28:47.000000000 +0100 +@@ -31,13 +31,9 @@ if [ "$1" = "" ]; then exit 1 fi @@ -44,10 +44,14 @@ diff -up netpbm-10.47.06/editor/pamstretch-gen.security-scripts netpbm-10.47.06/ +tempfile=$(mktemp /tmp/pnmig.XXXXXXXXXX) || exit 1 trap 'rm -rf $tempdir' 0 1 3 15 - tempfile=$tempdir/pnmig -diff -up netpbm-10.47.06/editor/pnmmargin.security-scripts netpbm-10.47.06/editor/pnmmargin ---- netpbm-10.47.06/editor/pnmmargin.security-scripts 2009-12-13 20:26:58.000000000 +0100 -+++ netpbm-10.47.06/editor/pnmmargin 2009-12-16 19:04:05.000000000 +0100 +-tempfile=$tempdir/pnmig +- + if ! cat $2 >$tempfile 2>/dev/null; then + echo 'pamstretch-gen: error reading file' 1>&2 + exit 1 +diff -up netpbm-10.47.05/editor/pnmmargin.security-scripts netpbm-10.47.05/editor/pnmmargin +--- netpbm-10.47.05/editor/pnmmargin.security-scripts 2009-12-10 08:34:32.000000000 +0100 ++++ netpbm-10.47.05/editor/pnmmargin 2010-03-16 21:28:09.000000000 +0100 @@ -11,15 +11,11 @@ # documentation. This software is provided "as is" without express or # implied warranty. @@ -86,9 +90,9 @@ diff -up netpbm-10.47.06/editor/pnmmargin.security-scripts netpbm-10.47.06/edito - - +rm -rf "$tmpdir" -diff -up netpbm-10.47.06/editor/ppmfade.security-scripts netpbm-10.47.06/editor/ppmfade ---- netpbm-10.47.06/editor/ppmfade.security-scripts 2009-12-13 20:26:58.000000000 +0100 -+++ netpbm-10.47.06/editor/ppmfade 2009-12-16 18:59:17.000000000 +0100 +diff -up netpbm-10.47.05/editor/ppmfade.security-scripts netpbm-10.47.05/editor/ppmfade +--- netpbm-10.47.05/editor/ppmfade.security-scripts 2009-12-10 08:34:32.000000000 +0100 ++++ netpbm-10.47.05/editor/ppmfade 2010-03-16 21:28:09.000000000 +0100 @@ -14,6 +14,7 @@ # #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- @@ -352,9 +356,9 @@ diff -up netpbm-10.47.06/editor/ppmfade.security-scripts netpbm-10.47.06/editor/ +system("rm $tmpdir/junk*$$.ppm"); exit(0); -diff -up netpbm-10.47.06/editor/ppmquantall.security-scripts netpbm-10.47.06/editor/ppmquantall ---- netpbm-10.47.06/editor/ppmquantall.security-scripts 2009-12-13 20:26:58.000000000 +0100 -+++ netpbm-10.47.06/editor/ppmquantall 2009-12-16 18:59:17.000000000 +0100 +diff -up netpbm-10.47.05/editor/ppmquantall.security-scripts netpbm-10.47.05/editor/ppmquantall +--- netpbm-10.47.05/editor/ppmquantall.security-scripts 2009-12-10 08:34:32.000000000 +0100 ++++ netpbm-10.47.05/editor/ppmquantall 2010-03-16 21:28:09.000000000 +0100 @@ -70,12 +70,8 @@ for i in ${files[@]}; do heights=(${heights[*]} `grep -v '^#' $i | sed '1d; s/.* //; 2q'`) done @@ -370,9 +374,9 @@ diff -up netpbm-10.47.06/editor/ppmquantall.security-scripts netpbm-10.47.06/edi pnmcat -topbottom -jleft -white ${files[@]} | pnmquant $newcolors > $all if [ $? != 0 ]; then -diff -up netpbm-10.47.06/editor/ppmshadow.security-scripts netpbm-10.47.06/editor/ppmshadow ---- netpbm-10.47.06/editor/ppmshadow.security-scripts 2009-12-13 20:26:58.000000000 +0100 -+++ netpbm-10.47.06/editor/ppmshadow 2009-12-16 18:59:17.000000000 +0100 +diff -up netpbm-10.47.05/editor/ppmshadow.security-scripts netpbm-10.47.05/editor/ppmshadow +--- netpbm-10.47.05/editor/ppmshadow.security-scripts 2009-12-10 08:34:32.000000000 +0100 ++++ netpbm-10.47.05/editor/ppmshadow 2010-03-16 21:28:09.000000000 +0100 @@ -72,9 +72,10 @@ sub makeConvolutionKernel($$) { diff --git a/netpbm.spec b/netpbm.spec index 723c3db..94560ba 100644 --- a/netpbm.spec +++ b/netpbm.spec @@ -1,7 +1,7 @@ Summary: A library for handling different graphics file formats Name: netpbm Version: 10.47.10 -Release: 1%{?dist} +Release: 2%{?dist} # See copyright_summary for details License: BSD and GPLv2 and IJG and MIT and Public Domain Group: System Environment/Libraries @@ -29,6 +29,7 @@ Patch15: netpbm-docfix.patch Patch16: netpbm-ppmfadeusage.patch Patch17: netpbm-fiasco-overflow.patch Patch18: netpbm-lz.patch +Patch19: netpbm-pnmmontagefix.patch Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: libjpeg-devel, libpng-devel, libtiff-devel, flex BuildRequires: libX11-devel, python, jasper-devel @@ -88,6 +89,7 @@ netpbm-progs. You'll also need to install the netpbm package. %patch16 -p1 -b .ppmfadeusage %patch17 -p1 -b .fiasco-overflow %patch18 -p1 -b .lz +%patch19 -p1 -b .pnmmmontagefix sed -i 's/STRIPFLAG = -s/STRIPFLAG =/g' config.mk.in @@ -188,13 +190,15 @@ rm -rf $RPM_BUILD_ROOT/usr/config_template # Don't ship the static library rm -f $RPM_BUILD_ROOT/%{_libdir}/lib*.a -# remove/symlink obsolete utilities +# remove/symlink/substitute obsolete utilities pushd $RPM_BUILD_ROOT%{_bindir} rm -f pgmtopbm pnmcomp -ln -s pamditherbw pgmtopbm ln -s pamcomp pnmcomp +echo -e '#!/bin/sh\npamditherbw $@ | pamtopnm\n' > pgmtopbm +chmod 0755 pgmtopbm popd + %clean rm -rf $RPM_BUILD_ROOT @@ -222,6 +226,11 @@ rm -rf $RPM_BUILD_ROOT %{_datadir}/netpbm/ %changelog +* Wed Mar 17 2010 Jindrich Novy 10.47.10-2 +- pgmtopbm should generate PBM, not PAM file +- forwardport pnmmontage from 10.35 to make it work +- fix pamstretch-gen + * Wed Feb 24 2010 Jindrich Novy 10.47.10-1 - update to 10.47.10 - fixes crash in pnmhistmap