/* gridunpack.c: extract a file from a gridpix */ /* * usage: gridunpack gpxfile\&tilenum\&smooth * (file number 1 is first file) * */ #include #include #include #include #include #include #include #include "gridpix.h" #include "utils.h" /* #define DEBUG 1 */ int main(int argc, char **argv, char **env) #ifndef SEPARATE { char *cp, *tp ; char *na[4] ; int gettile(int, char **, char **) ; printf("Content-type: image/jpeg\n\n") ; na[0] = argv[0] ; cp = malloc(strlen(argv[1]) * 2 + 100) ; strcpy(cp, GRIDROOT) ; #ifdef SUBDIR strncat(cp, argv[1], 12) ; strcat(cp, "/images/") ; #endif tp = index(argv[1], '\\') ; strncat(cp, argv[1], tp-argv[1]) ; strcat(cp, ".gpx") ; na[1] = cp ; cp = index(argv[1], '\\') ; na[2] = cp + 2 ; cp = index(na[2], '\\') ; *cp = '\0' ; na[3] = cp+2 ; return gettile(4, na, env) ; } int gettile(int argc, char **argv, char **env) #endif { char *progname ; char *filename ; unsigned long filenum ; char *buf ; FILE *fp ; m_int_t offset, size, s ; off_t offset1, size1 ; /* type 1 */ f_int_t offset2, size2 ; /* type 2 */ struct gridpix gp ; int gpxtype ; int minx, miny, maxx, maxy ; struct jpeg_compress_struct cinfo ; struct jpeg_decompress_struct dinfo ; struct jpeg_error_mgr cerr, derr ; JSAMPROW *scanline ; int i, j, k, l ; char *debug = getenv("DEBUG") ; int ratio ; int smooth ; ratio = 1 ; minx = miny = maxx = maxy = -1 ; /* sentinel */ progname = argv[0] ; if (argc != 4 && argc != 8) { fprintf(stderr, "usage: %s file num [minx miny maxx maxy]\n", progname) ; exit(1) ; } filename = argv[1] ; filenum = atoi(argv[2]) ; smooth = atoi(argv[3]) ; if (argc == 8) { minx = atoi(argv[4]) ; miny = atoi(argv[5]) ; maxx = atoi(argv[6]) ; maxy = atoi(argv[7]) ; if (minx < 0) { fprintf(stderr, "minx is less than 0 (%d)\n", minx) ; exit(1) ; } if (miny < 0) { fprintf(stderr, "miny is less than 0 (%d)\n", miny) ; exit(1) ; } } if ((fp = fopen(filename, "r")) == NULL) { fprintf(stderr, "\"%s\"", filename) ; perror("") ; exit(1) ; } if ((gpxtype = readheader(&gp, fp)) == 0) { exit(1) ; } if (filenum <= 0) { fprintf(stderr, "error: invalid index number %lu\n", filenum) ; exit(1) ; } if (filenum > gp.header.numfiles) { int width, height, tilewidth, tileheight, numfiles ; int xnum, ynum, oxnum, oynum, row, col ; int xsize, ysize ; tilewidth = gp.header.tilewidth ; tileheight = gp.header.tileheight ; oxnum = (gp.header.width+tilewidth-1)/tilewidth ; oynum = (gp.header.height+tileheight-1)/tileheight ; numfiles = gp.header.numfiles ; for (i = gp.header.layers+1 ; ; i++) { ratio *= gp.header.ratio ; width = gp.header.width * ratio ; height = gp.header.height * ratio ; xnum = (width+tilewidth-1) / tilewidth ; ynum = (height+tileheight-1) / tileheight ; if (numfiles + xnum*ynum>= filenum) break ; numfiles += xnum*ynum ; } row = (filenum - numfiles - 1) / xnum ; col = (filenum - numfiles - 1) % xnum ; xsize = tilewidth ; ysize = tileheight ; if (row + 1 == ynum) { ysize = (height%tileheight) / ratio ; if (ysize == 0) ysize = tileheight/ratio ; } if (col + 1 == xnum) { xsize = (width%tilewidth) / ratio ; if (xsize == 0) xsize = tilewidth/ratio ; } filenum = gp.header.numfiles - oxnum*oynum + (row/ratio)*oxnum + (col/ratio) + 1 ; minx = tilewidth * (col%ratio) / ratio ; if (col + 1 == xnum) maxx = minx + xsize - 1 ; else maxx = tilewidth * (col%ratio+1) / ratio - 1 ; miny = tileheight * (row%ratio) / ratio ; if (row + 1 == ynum) maxy = miny + ysize - 1 ; else maxy = tileheight * (row%ratio+1) / ratio - 1 ; if (debug) fprintf(stderr, "filenum %ld, %d, coord (%d, %d), (%d %d %d %d) %d %d %d %d\n", filenum, ratio, row, col, minx, miny, maxx, maxy, oxnum, oynum, xsize, ysize) ; } if (debug) exit(1) ; if (gpxtype == 1) { if (fseek(fp, gp.header.headersize + (filenum-1) * sizeof(offset1), SEEK_SET) < 0) { fprintf(stderr, "error: can't seek %qd bytes\n", gp.header.headersize + (filenum-1) * sizeof(offset1)) ; exit(1) ; } if ((s = fread(&offset1, sizeof(offset1), 1, fp)) < 1) { fprintf(stderr, "error: can't read the offset\n") ; exit(1) ; } if ((s = fread(&size1, sizeof(size1), 1, fp)) < 1) { fprintf(stderr, "error: can't read the offset\n") ; exit(1) ; } size = size1 ; offset = offset1 ; } else { /* type 2 */ if (fseek(fp, gp.header.headersize + (filenum-1) * sizeof(offset2), SEEK_SET) < 0) { fprintf(stderr, "error: can't seek %qd bytes\n", gp.header.headersize + (filenum-1) * sizeof(offset2)) ; exit(1) ; } if ((s = fread(&offset2, sizeof(offset2), 1, fp)) < 1) { fprintf(stderr, "error: can't read the offset\n") ; exit(1) ; } if ((s = fread(&size2, sizeof(size2), 1, fp)) < 1) { fprintf(stderr, "error: can't read the offset\n") ; exit(1) ; } fromfint(&size, size2) ; fromfint(&offset, offset2) ; } size -= offset ; #ifdef DEBUG fprintf(stderr, "number of files: %lu, file number: %lu\n", gp.header.numfiles, filenum) ; fprintf(stderr, "offset = %qd, size = %qd\n", offset, size) ; #endif if (fseek(fp, offset, SEEK_SET) < 0) { fprintf(stderr, "error: can't seek %qd bytes\n", offset) ; exit(1) ; } buf = malloc(size) ; if (buf == 0) { fprintf(stderr, "panic: cannot allocate %qd bytes", size) ; exit(1) ; } if (minx == -1) { /* no subtiling */ if ((s = fread(buf, 1, size, fp)) < size) { perror("read") ; exit(1) ; } fwrite(buf, 1, size, stdout) ; } else { dinfo.err = jpeg_std_error(&derr) ; jpeg_create_decompress(&dinfo) ; cinfo.err = jpeg_std_error(&cerr) ; jpeg_create_compress(&cinfo) ; jpeg_stdio_src(&dinfo, fp) ; jpeg_stdio_dest(&cinfo, stdout) ; jpeg_read_header(&dinfo, TRUE) ; jpeg_start_decompress(&dinfo) ; if (maxx > dinfo.output_width) { printf("error: requested width (%d) is greater than image's (%d)\n", maxx, dinfo.output_width) ; exit(1) ; } if (maxy > dinfo.output_height) { printf("error: requested height (%d) is greater than image's (%d)\n", maxy, dinfo.output_height) ; exit(1) ; } if (smooth) { cinfo.image_width = (maxx - minx + 1) * ratio ; cinfo.image_height = (maxy - miny + 1) * ratio ; } else { cinfo.image_width = (maxx - minx + 1) ; cinfo.image_height = (maxy - miny + 1) ; } cinfo.input_components = dinfo.out_color_components ; cinfo.in_color_space = JCS_RGB ; jpeg_set_defaults(&cinfo) ; if (smooth) cinfo.smoothing_factor = (50 + 10 * ratio < 100) ? 50 + 10 * ratio : 100 ; jpeg_start_compress(&cinfo, TRUE) ; scanline = xmalloc(dinfo.output_height * sizeof(scanline[0])) ; if (smooth) scanline[0] = xmalloc(3 * dinfo.output_width * dinfo.output_height * ratio) ; else scanline[0] = xmalloc(3 * dinfo.output_width * dinfo.output_height) ; for (i = 0 ; i < dinfo.output_height ; i++) { jpeg_read_scanlines(&dinfo, scanline+i, 1) ; if (smooth) { if (ratio > 1) for (j = dinfo.output_width-1 ; j >= 0 ; j--) for (k = ratio-1 ; k >= 0 ; k--) for (l = 0 ; l < 3 ; l++) scanline[i][(j*ratio+k)*3+l] = scanline[i][j*3+l] ; if (i < dinfo.output_height-1) scanline[i+1] = scanline[i] + 3 * dinfo.output_width * ratio ; } else { if (i < dinfo.output_height-1) scanline[i+1] = scanline[i] + 3 * dinfo.output_width ; } } for (i = miny ; i <= maxy ; i++) { if (smooth) { scanline[i] += 3 * minx * ratio ; for (k = 0 ; k < ratio ; k++) jpeg_write_scanlines(&cinfo, scanline+i, 1) ; } else { scanline[i] += 3 * minx ; jpeg_write_scanlines(&cinfo, scanline+i, 1) ; } } jpeg_finish_decompress(&dinfo) ; jpeg_finish_compress(&cinfo) ; jpeg_destroy_decompress(&dinfo) ; jpeg_destroy_compress(&cinfo) ; } fclose(fp) ; exit(0) ; }