/* gridpack.c: create a gridpix from a ppm file */ /* usage: gridpack [ppmfile] */ #define BufSize 1024 #include #include #include #include #include #include #include #include #include #include "gridpix.h" #include "utils.h" /* Default values */ #define TileWidth 144 #define TileHeight 144 #define Layers 4 #define Ratio 2 #define Quality 75 /* #define DEBUG 1 */ void usage(char *progname) ; int main(int argc, char **argv) { char *progname ; pixval maxval ; pixel **ippm, **tppm ; int numfiles ; char *inputfile = NULL ; m_int_t offset ; FILE *ifp, *ofp ; struct gridpix gp ; struct jpeg_compress_struct cinfo ; struct jpeg_error_mgr jerr ; JSAMPROW scanline[1] ; int tmpwidth, tmpheight, layer, filenum ; int i, j, x, y, xmax, ymax, xsize, ysize ; int factor ; int width, height, tilewidth, tileheight ; int quality ; char *outputfile = NULL ; m_int_t *offsets = NULL ; f_int_t *offsets2 = NULL ; int layers = Layers ; tilewidth = TileWidth ; tileheight = TileHeight ; quality = Quality ; ifp = stdin ; progname = argv[0] ; while (argc > 1) { if (!strcmp(argv[1], "-t")) { if (argc < 3) usage(progname) ; tilewidth = tileheight = atoi(argv[2]) ; argc-- ; argv++ ; } else if (!strcmp(argv[1], "-q")) { if (argc < 3) usage(progname) ; quality = atoi(argv[2]) ; argc-- ; argv++ ; } else if (!strcmp(argv[1], "-o")) { if (argc < 3) usage(progname) ; outputfile = argv[2] ; argc-- ; argv++ ; } else if (!strcmp(argv[1], "-l")) { if (argc < 3) usage(progname) ; layers = atoi(argv[2]) ; argc-- ; argv++ ; } else if (!strcmp(argv[1], "-h")) { usage(progname) ; exit(0) ; } else inputfile = argv[1] ; argc-- ; argv++ ; } if (inputfile == NULL && outputfile == NULL) { fprintf(stderr, "error: must specify at least one of input or output\n") ; exit(1) ; } memcpy(gp.header.magic, Magic2, 4) ; gp.header.headersize = sizeof(struct gridheader2) ; gp.header.tilewidth = tilewidth ; gp.header.tileheight = tileheight ; gp.header.layers = layers ; gp.header.ratio = Ratio ; if (inputfile) { if ((ifp = fopen(inputfile, "r")) == NULL) { fprintf(stderr, "\"%s\"", inputfile) ; perror("") ; exit(1) ; } if (outputfile == NULL) { if (strcmp(inputfile + strlen(inputfile) - strlen(".ppm"), ".ppm")) { fprintf(stderr, "error: inputfile doesn't end with \".ppm\"\n") ; exit(1) ; } outputfile = strdup(inputfile) ; strcpy(outputfile + strlen(outputfile) - strlen(".ppm"), ".gpx") ; } } if ((ofp = fopen(outputfile, "w")) == NULL) { fprintf(stderr, "\"%s\"", outputfile) ; perror("") ; exit(1) ; } ippm = ppm_readppm(ifp, &width, &height, &maxval) ; gp.header.width = width ; gp.header.height = height ; scanline[0] = malloc(3 * gp.header.tilewidth) ; numfiles = 0 ; for (layer = 0 ; layer < gp.header.layers ; layer++) { factor = pow(gp.header.ratio, gp.header.layers-layer-1) ; tmpwidth = gp.header.width / factor ; tmpheight = gp.header.height / factor ; numfiles += ((tmpwidth + gp.header.tilewidth - 1) / gp.header.tilewidth) * ((tmpheight + gp.header.tileheight - 1) / gp.header.tileheight) ; gp.header.layersize[layer] = numfiles ; } for (; layer < MaxLayers ; layer++) gp.header.layersize[layer] = gp.header.layersize[layer-1] ; gp.header.numfiles = numfiles ; gp.offsets[0] = offset = sizeof(gp) + numfiles * sizeof(offsets2[0]) ; offsets = xmalloc(numfiles * sizeof(offsets[0])) ; offsets2 = xmalloc(numfiles * sizeof(offsets2[0])) ; /* First write the jpeg files, then come back to write the header */ fseek(ofp, offset, SEEK_SET) ; tppm = ppm_allocarray(gp.header.tilewidth, gp.header.tileheight) ; for (layer = 0, filenum = 0 ; layer < gp.header.layers ; layer++) { factor = pow(gp.header.ratio, gp.header.layers-layer-1) ; tmpwidth = gp.header.width / factor ; tmpheight = gp.header.height / factor ; xmax = (tmpwidth + gp.header.tilewidth - 1) / gp.header.tilewidth ; ymax = (tmpheight + gp.header.tileheight - 1) / gp.header.tileheight ; for (y = 0 ; y < ymax ; y++) { if (y == ymax-1) { ysize = tmpheight % gp.header.tileheight ; if (ysize == 0) ysize = gp.header.tileheight ; } else ysize = gp.header.tileheight ; for (x = 0 ; x < xmax ; x++) { if (x == xmax-1) { xsize = tmpwidth % gp.header.tilewidth ; if (xsize == 0) xsize = gp.header.tilewidth ; } else xsize = gp.header.tilewidth ; for (i = 0 ; i < ysize ; i++) { for (j = 0 ; j < xsize ; j++) { int tmpr, tmpg, tmpb ; pixel p ; int k, l ; tmpr = tmpg = tmpb = 0 ; for (k = 0 ; k < factor ; k++) { for (l = 0 ; l < factor ; l++) { p = ippm[(y*gp.header.tileheight+i)*factor+k][(x*gp.header.tilewidth+j)*factor+l] ; tmpr += PPM_GETR(p) ; tmpg += PPM_GETG(p) ; tmpb += PPM_GETB(p) ; } } tmpr /= factor*factor ; tmpg /= factor*factor ; tmpb /= factor*factor ; PPM_ASSIGN(tppm[i][j], tmpr, tmpg, tmpb) ; } } cinfo.err = jpeg_std_error(&jerr) ; jpeg_create_compress(&cinfo) ; jpeg_stdio_dest(&cinfo, ofp) ; cinfo.image_width = xsize ; cinfo.image_height = ysize ; cinfo.input_components = 3 ; cinfo.in_color_space = JCS_RGB ; jpeg_set_defaults(&cinfo) ; /* create progressive JPEGS */ /* doesn't work ? jpeg_simple_progression(&cinfo) ; */ jpeg_set_quality(&cinfo, quality, TRUE) ; jpeg_start_compress(&cinfo, TRUE) ; for (i = 0 ; i < ysize ; i++) { for (j = 0 ; j < xsize ; j++) { pixel p = tppm[i][j] ; scanline[0][j*3] = PPM_GETR(p) ; scanline[0][j*3+1] = PPM_GETG(p) ; scanline[0][j*3+2] = PPM_GETB(p) ; } jpeg_write_scanlines(&cinfo, scanline, 1) ; } jpeg_finish_compress(&cinfo) ; jpeg_destroy_compress(&cinfo) ; offsets[filenum] = ftell(ofp) ; filenum++ ; } } } ppm_freearray(tppm, gp.header.tileheight) ; writeheader(&gp, ofp) ; /* note offset to first file is already written in writeheader */ for (i = 0 ; i < numfiles ; i++) tofint(&offsets2[i], offsets[i]) ; fwrite(offsets2, sizeof(offsets2[0]), numfiles, ofp) ; return 0 ; } void usage(char *progname) { fprintf(stderr, "usage: %s [-t tilesize] [-q quality] [-l numlayers] [-o outputfile] [inputfile]\n", progname) ; exit(1) ; }